// COPYRIGHT (C) Tom. ALL RIGHTS RESERVED.
// THE AntdUI PROJECT IS AN WINFORM LIBRARY LICENSED UNDER THE Apache-2.0 License.
// LICENSED UNDER THE Apache License, VERSION 2.0 (THE "License")
// YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE License.
// YOU MAY OBTAIN A COPY OF THE LICENSE AT
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE
// DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
// SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND
// LIMITATIONS UNDER THE License.
// GITEE: https://gitee.com/antdui/AntdUI
// GITHUB: https://github.com/AntdUI/AntdUI
// CSDN: https://blog.csdn.net/v_132
// QQ: 17379620
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
namespace AntdUI
{
///
/// Select 选择器
///
/// 下拉选择器。
[Description("Select 选择器")]
[ToolboxItem(true)]
[DefaultEvent("SelectedIndexChanged")]
public class Select : Input, SubLayeredForm
{
#region 属性
protected override bool BanInput => _list;
bool _list = false;
///
/// 是否列表样式
///
[Description("是否列表样式"), Category("外观"), DefaultValue(false)]
public bool List
{
get => _list;
set
{
if (_list == value) return;
_list = value;
ReadShowCaret = value;
if (value) ShowCaret = false;
}
}
///
/// 菜单弹出位置
///
[Description("菜单弹出位置"), Category("行为"), DefaultValue(TAlignFrom.BL)]
public TAlignFrom Placement { get; set; } = TAlignFrom.BL;
///
/// 是否列表自动宽度
///
[Description("是否列表自动宽度"), Category("行为"), DefaultValue(false)]
public bool ListAutoWidth { get; set; } = false;
///
/// 列表最多显示条数
///
[Description("列表最多显示条数"), Category("行为"), DefaultValue(4)]
public int MaxCount { get; set; } = 4;
///
/// 下拉箭头是否显示
///
[Description("下拉箭头是否显示"), Category("外观"), DefaultValue(false)]
public bool DropDownArrow { get; set; } = false;
///
/// 点击到最里层(无节点才能点击)
///
[Description("点击到最里层(无节点才能点击)"), Category("行为"), DefaultValue(false)]
public bool ClickEnd { get; set; } = false;
///
/// 焦点时展开下拉
///
[Description("焦点时展开下拉"), Category("行为"), DefaultValue(true)]
public bool FocusExpandDropdown { get; set; } = true;
///
/// 点击切换下拉
///
[Description("点击切换下拉"), Category("行为"), DefaultValue(true)]
public bool ClickSwitchDropdown { get; set; } = true;
#region 数据
BaseCollection? items;
///
/// 数据
///
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor", typeof(UITypeEditor))]
[Description("集合"), Category("数据")]
public BaseCollection Items
{
get
{
items ??= new BaseCollection();
return items;
}
set => items = value;
}
#region 操作值
///
/// 选中序号
///
[Description("选中序号"), Category("数据"), DefaultValue(-1)]
public int SelectedIndex
{
get => selectedIndex;
set
{
if (selectedIndex == value) return;
if (items == null || items.Count == 0 || value == -1) ChangeValueNULL();
else
{
var obj = items[value];
if (obj == null) return;
ChangeValue(value, obj);
}
if (_list) Invalidate();
}
}
///
/// 选中值
///
[Browsable(false)]
[Description("选中值"), Category("数据"), DefaultValue(null)]
public object? SelectedValue
{
get => selectedValue;
set
{
if (selectedValue == value) return;
if (value == null || items == null || items.Count == 0) ChangeValueNULL();
else SetChangeValue(items, value);
if (_list) Invalidate();
}
}
int selectedIndexX = -1;
int selectedIndex = -1;
object? selectedValue = null;
void ChangeValueNULL()
{
Text = "";
selectedValue = null;
selectedIndex = -1;
SelectedValueChanged?.Invoke(this, new ObjectNEventArgs(selectedValue));
SelectedIndexChanged?.Invoke(this, new IntEventArgs(selectedIndex));
}
void ChangeValue(int value, object? obj)
{
selectedIndex = value;
if (obj is SelectItem it)
{
selectedValue = it.Tag;
Text = it.Text;
}
else
{
selectedValue = obj;
if (obj == null) Text = "";
else Text = obj.ToString() ?? "";
}
SelectedValueChanged?.Invoke(this, new ObjectNEventArgs(selectedValue));
SelectedIndexChanged?.Invoke(this, new IntEventArgs(selectedIndex));
}
void SetChangeValue(BaseCollection items, object val)
{
for (var i = 0; i < items.Count; i++)
{
var item = items[i];
if (val.Equals(item))
{
ChangeValue(i, item);
return;
}
else if (item is SelectItem it && it.Tag.Equals(val))
{
ChangeValue(i, item);
return;
}
else if (item is GroupSelectItem group && group.Sub != null && group.Sub.Count > 0)
{
foreach (var sub in group.Sub)
{
if (val.Equals(sub))
{
ChangeValue(i, sub);
return;
}
else if (sub is SelectItem it2 && it2.Tag.Equals(val))
{
ChangeValue(i, sub);
return;
}
}
}
}
ChangeValue(items.IndexOf(val), val);
}
void ChangeValue(int x, int y, object obj)
{
selectedIndexX = x;
selectedIndex = y;
if (obj is SelectItem it)
{
selectedValue = it.Tag;
Text = it.Text;
}
else
{
selectedValue = obj;
Text = obj.ToString() ?? "";
}
SelectedValueChanged?.Invoke(this, new ObjectNEventArgs(selectedValue));
SelectedIndexsChanged?.Invoke(this, new IntXYEventArgs(selectedIndexX, selectedIndex));
}
internal void DropDownChange(int i)
{
selectedIndexX = 0;
if (items == null || items.Count == 0) ChangeValueNULL();
else ChangeValue(i, items[i]);
TextFocus = false;
select_x = 0;
subForm = null;
}
internal bool DropDownChange()
{
return SelectedIndexsChanged == null;
}
internal void DropDownChange(int x, int y, object value)
{
ChangeValue(x, y, value);
TextFocus = false;
select_x = 0;
subForm = null;
}
#endregion
///
/// SelectedIndex 属性值更改时发生
///
[Description("SelectedIndex 属性值更改时发生"), Category("行为")]
public event IntEventHandler? SelectedIndexChanged = null;
///
/// 多层树结构更改时发生
///
[Description("多层树结构更改时发生"), Category("行为")]
public event IntXYEventHandler? SelectedIndexsChanged = null;
///
/// SelectedValue 属性值更改时发生
///
[Description("SelectedValue 属性值更改时发生"), Category("行为")]
public event ObjectNEventHandler? SelectedValueChanged = null;
public delegate IList