2017-06-29 18:27:48 +02:00
|
|
|
|
/// Copyright 2017 Kopano b.v.
|
2016-12-21 12:53:16 +01:00
|
|
|
|
///
|
|
|
|
|
/// 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,
|
|
|
|
|
/// as published by the Free Software Foundation.
|
|
|
|
|
///
|
|
|
|
|
/// This program is distributed in the hope that it will be useful,
|
|
|
|
|
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
|
|
|
|
/// GNU Affero General Public License for more details.
|
|
|
|
|
///
|
|
|
|
|
/// You should have received a copy of the GNU Affero General Public License
|
|
|
|
|
/// along with this program.If not, see<http://www.gnu.org/licenses/>.
|
|
|
|
|
///
|
|
|
|
|
/// Consult LICENSE file for details
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Data;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using Acacia.ZPush;
|
|
|
|
|
using Acacia.Features.GAB;
|
|
|
|
|
using Acacia.Stubs;
|
|
|
|
|
using System.Collections;
|
2017-06-20 15:26:16 +02:00
|
|
|
|
using Acacia.Controls;
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
|
|
|
|
namespace Acacia.UI
|
|
|
|
|
{
|
2017-06-29 18:27:48 +02:00
|
|
|
|
public partial class GABLookupControl : KComboBoxCustomDraw
|
2016-12-21 12:53:16 +01:00
|
|
|
|
{
|
2017-06-29 18:27:48 +02:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-21 12:53:16 +01:00
|
|
|
|
public GABLookupControl() : this(null)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public GABLookupControl(GABHandler gab)
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
2017-06-29 18:27:48 +02:00
|
|
|
|
GAB = gab;
|
2016-12-21 12:53:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Properties and events
|
|
|
|
|
|
2017-06-20 15:26:16 +02:00
|
|
|
|
#region SelectedUser
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
|
|
|
|
public class SelectedUserEventArgs : EventArgs
|
|
|
|
|
{
|
|
|
|
|
public readonly GABUser SelectedUser;
|
|
|
|
|
public readonly bool IsChosen;
|
|
|
|
|
|
|
|
|
|
public SelectedUserEventArgs(GABUser selectedUser, bool isChosen)
|
|
|
|
|
{
|
|
|
|
|
this.SelectedUser = selectedUser;
|
|
|
|
|
this.IsChosen = isChosen;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public delegate void SelectedUserEventHandler(object source, SelectedUserEventArgs e);
|
|
|
|
|
|
|
|
|
|
[Category("Behavior")]
|
|
|
|
|
public event SelectedUserEventHandler SelectedUserChanged;
|
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
private GABUser _selectedUser;
|
2016-12-21 12:53:16 +01:00
|
|
|
|
public GABUser SelectedUser
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
2017-06-29 18:27:48 +02:00
|
|
|
|
return _selectedUser;
|
2016-12-21 12:53:16 +01:00
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
2017-06-29 18:27:48 +02:00
|
|
|
|
_selectedUser = null;
|
|
|
|
|
Select(value);
|
2016-12-21 12:53:16 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
protected override void OnTextChanged(EventArgs e)
|
2016-12-21 12:53:16 +01:00
|
|
|
|
{
|
2017-06-29 18:27:48 +02:00
|
|
|
|
base.OnTextChanged(e);
|
|
|
|
|
_selectedUser = string.IsNullOrEmpty(Text) ? null : new GABUser(Text);
|
|
|
|
|
SelectedUserChanged?.Invoke(this, new SelectedUserEventArgs(_selectedUser, false));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnSelectedItemChanged()
|
|
|
|
|
{
|
|
|
|
|
_selectedUser = (GABUser)SelectedItem?.Item;
|
|
|
|
|
SelectedUserChanged?.Invoke(this, new SelectedUserEventArgs(_selectedUser, true));
|
2016-12-21 12:53:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region GAB
|
|
|
|
|
|
|
|
|
|
private GABHandler _gab;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The GAB. This must be set to allow lookups
|
|
|
|
|
/// </summary>
|
|
|
|
|
public GABHandler GAB
|
|
|
|
|
{
|
|
|
|
|
get { return _gab; }
|
2017-06-20 15:26:16 +02:00
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (_gab != value)
|
|
|
|
|
{
|
|
|
|
|
_gab = value;
|
2017-06-29 18:27:48 +02:00
|
|
|
|
DataSource = _gab == null ? null : new GABDataSource(_gab);
|
2017-06-20 15:26:16 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-12-21 12:53:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
public GABUser LookupExact(string username)
|
2016-12-21 12:53:16 +01:00
|
|
|
|
{
|
2017-06-29 18:27:48 +02:00
|
|
|
|
string s = username.ToLower();
|
2016-12-21 12:53:16 +01:00
|
|
|
|
if (DataSource != null)
|
|
|
|
|
{
|
2017-06-29 18:27:48 +02:00
|
|
|
|
foreach(GABUser user in DataSource.Items)
|
|
|
|
|
{
|
|
|
|
|
if (
|
|
|
|
|
user.FullName?.ToLower().Equals(s) == true ||
|
|
|
|
|
user.UserName?.ToLower().Equals(s) == true ||
|
|
|
|
|
user.EmailAddress?.ToLower().Equals(s) == true
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
return user;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-12-21 12:53:16 +01:00
|
|
|
|
}
|
2017-06-29 18:27:48 +02:00
|
|
|
|
|
|
|
|
|
return new GABUser(username);
|
2016-12-21 12:53:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
#region Rendering
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
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;
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
protected override void OnMeasureItem(MeasureItemEventArgs e)
|
2016-12-21 12:53:16 +01:00
|
|
|
|
{
|
2017-06-29 18:27:48 +02:00
|
|
|
|
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, item.EmailAddress, 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;
|
2016-12-21 12:53:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
protected override void OnDrawItem(DrawItemEventArgs e)
|
2016-12-21 12:53:16 +01:00
|
|
|
|
{
|
2017-06-29 18:27:48 +02:00
|
|
|
|
GABUser item = (GABUser)e.Item;
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
// Draw the background
|
|
|
|
|
e.DrawBackground();
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
// 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);
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
// 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);
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
// Draw the username top-right
|
|
|
|
|
pt.X = e.Bounds.Right - loginSize.Width - ItemPadding.Right;
|
|
|
|
|
TextRenderer.DrawText(e.Graphics, item.UserName, Font, pt, e.ForeColor);
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
// 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, item.EmailAddress, Font, pt, e.ForeColor);
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
2017-06-29 18:27:48 +02:00
|
|
|
|
// Draw a separator line
|
|
|
|
|
if (e.Index < DisplayItemCount - 1)
|
2016-12-21 12:53:16 +01:00
|
|
|
|
{
|
2017-06-29 18:27:48 +02:00
|
|
|
|
int lineY = e.Bounds.Bottom - 1 - BorderThickness - BorderPadding.Bottom;
|
|
|
|
|
e.Graphics.DrawLine(Pens.LightGray, BorderPadding.Left, lineY, e.Bounds.Width - BorderPadding.Right, lineY);
|
2017-02-08 15:40:48 +01:00
|
|
|
|
}
|
2016-12-21 12:53:16 +01:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|