298 lines
11 KiB
C#
298 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using CadParamPluging.Common;
|
|
|
|
namespace CadParamPluging.UI
|
|
{
|
|
public class ParamDefinitionForm : Form
|
|
{
|
|
private readonly bool _isEdit;
|
|
private readonly TextBox _txtKey;
|
|
private readonly TextBox _txtLabel;
|
|
private readonly ComboBox _cbType;
|
|
private readonly CheckBox _chkRequired;
|
|
private readonly TextBox _txtHint;
|
|
private readonly TextBox _txtDefault;
|
|
private readonly TextBox _txtMin;
|
|
private readonly TextBox _txtMax;
|
|
private readonly TextBox _txtEnumOptions;
|
|
private readonly TextBox _txtGroup;
|
|
private readonly NumericUpDown _numOrder;
|
|
|
|
public ParamDefinition Result { get; private set; }
|
|
|
|
public ParamDefinitionForm(string title, ParamDefinition initial, bool isEdit)
|
|
{
|
|
_isEdit = isEdit;
|
|
|
|
Text = title;
|
|
Size = new Size(520, 520);
|
|
StartPosition = FormStartPosition.CenterParent;
|
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
|
MaximizeBox = false;
|
|
MinimizeBox = false;
|
|
ShowInTaskbar = false;
|
|
|
|
var def = (initial ?? new ParamDefinition()).Clone();
|
|
def.Normalize();
|
|
|
|
var layout = new TableLayoutPanel
|
|
{
|
|
Dock = DockStyle.Fill,
|
|
Padding = new Padding(10),
|
|
ColumnCount = 2,
|
|
RowCount = 12,
|
|
AutoSize = true
|
|
};
|
|
layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
|
|
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f));
|
|
|
|
_txtKey = new TextBox { Width = 260, Text = def.Key };
|
|
_txtLabel = new TextBox { Width = 260, Text = def.Label };
|
|
_cbType = new ComboBox { DropDownStyle = ComboBoxStyle.DropDownList, Width = 260 };
|
|
_cbType.Items.AddRange(Enum.GetNames(typeof(ParamValueType)));
|
|
_cbType.SelectedItem = def.Type.ToString();
|
|
_cbType.SelectedIndexChanged += (_, __) => UpdateTypeUi();
|
|
|
|
_chkRequired = new CheckBox { Text = "必填", Checked = def.Required, AutoSize = true };
|
|
_txtHint = new TextBox { Width = 260, Text = def.Hint, Multiline = true, Height = 60, ScrollBars = ScrollBars.Vertical };
|
|
_txtDefault = new TextBox { Width = 260, Text = def.DefaultValue };
|
|
_txtMin = new TextBox { Width = 260, Text = def.Min };
|
|
_txtMax = new TextBox { Width = 260, Text = def.Max };
|
|
_txtEnumOptions = new TextBox { Width = 260, Height = 120, Multiline = true, ScrollBars = ScrollBars.Vertical };
|
|
_txtEnumOptions.Text = string.Join(Environment.NewLine, def.EnumOptions ?? new List<string>());
|
|
_txtGroup = new TextBox { Width = 260, Text = def.Group };
|
|
_numOrder = new NumericUpDown { Width = 120, Minimum = -100000, Maximum = 100000, Value = def.Order };
|
|
|
|
if (_isEdit)
|
|
{
|
|
_txtKey.ReadOnly = true;
|
|
}
|
|
|
|
var row = 0;
|
|
layout.Controls.Add(new Label { Text = "Key(英文)", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
|
|
layout.Controls.Add(_txtKey, 1, row++);
|
|
|
|
layout.Controls.Add(new Label { Text = "Label(中文)", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
|
|
layout.Controls.Add(_txtLabel, 1, row++);
|
|
|
|
layout.Controls.Add(new Label { Text = "类型", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
|
|
layout.Controls.Add(_cbType, 1, row++);
|
|
|
|
layout.Controls.Add(new Label { Text = "", AutoSize = true }, 0, row);
|
|
layout.Controls.Add(_chkRequired, 1, row++);
|
|
|
|
layout.Controls.Add(new Label { Text = "提示/填写方式", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
|
|
layout.Controls.Add(_txtHint, 1, row++);
|
|
|
|
layout.Controls.Add(new Label { Text = "默认值", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
|
|
layout.Controls.Add(_txtDefault, 1, row++);
|
|
|
|
layout.Controls.Add(new Label { Text = "最小值(数字)", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
|
|
layout.Controls.Add(_txtMin, 1, row++);
|
|
|
|
layout.Controls.Add(new Label { Text = "最大值(数字)", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
|
|
layout.Controls.Add(_txtMax, 1, row++);
|
|
|
|
layout.Controls.Add(new Label { Text = "枚举选项(每行一项)", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
|
|
layout.Controls.Add(_txtEnumOptions, 1, row++);
|
|
|
|
layout.Controls.Add(new Label { Text = "分组", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
|
|
layout.Controls.Add(_txtGroup, 1, row++);
|
|
|
|
layout.Controls.Add(new Label { Text = "排序", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
|
|
layout.Controls.Add(_numOrder, 1, row++);
|
|
|
|
var btnPanel = new FlowLayoutPanel
|
|
{
|
|
Dock = DockStyle.Fill,
|
|
FlowDirection = FlowDirection.RightToLeft,
|
|
AutoSize = true
|
|
};
|
|
var btnCancel = new Button { Text = "取消", DialogResult = DialogResult.Cancel };
|
|
var btnOk = new Button { Text = "确定" };
|
|
btnOk.Click += (_, __) => OnOk();
|
|
btnPanel.Controls.Add(btnCancel);
|
|
btnPanel.Controls.Add(btnOk);
|
|
|
|
layout.Controls.Add(btnPanel, 0, row);
|
|
layout.SetColumnSpan(btnPanel, 2);
|
|
|
|
Controls.Add(layout);
|
|
AcceptButton = btnOk;
|
|
CancelButton = btnCancel;
|
|
|
|
UpdateTypeUi();
|
|
}
|
|
|
|
private void UpdateTypeUi()
|
|
{
|
|
var type = GetSelectedType();
|
|
var showEnum = type == ParamValueType.Enum;
|
|
_txtEnumOptions.Enabled = showEnum;
|
|
|
|
var showMinMax = type == ParamValueType.Int || type == ParamValueType.Double;
|
|
_txtMin.Enabled = showMinMax;
|
|
_txtMax.Enabled = showMinMax;
|
|
}
|
|
|
|
private ParamValueType GetSelectedType()
|
|
{
|
|
var selected = _cbType.SelectedItem as string;
|
|
if (Enum.TryParse(selected, out ParamValueType t))
|
|
{
|
|
return t;
|
|
}
|
|
|
|
return ParamValueType.String;
|
|
}
|
|
|
|
private void OnOk()
|
|
{
|
|
var key = (_txtKey.Text ?? string.Empty).Trim();
|
|
var label = (_txtLabel.Text ?? string.Empty).Trim();
|
|
|
|
if (key.Length == 0)
|
|
{
|
|
MessageBox.Show(this, "Key 不能为空。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
if (!IsValidKey(key))
|
|
{
|
|
MessageBox.Show(this, "Key 格式不合法:必须以字母开头,仅允许字母/数字/下划线。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
if (label.Length == 0)
|
|
{
|
|
MessageBox.Show(this, "Label 不能为空。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
var type = GetSelectedType();
|
|
|
|
var def = new ParamDefinition
|
|
{
|
|
Key = key,
|
|
Label = label,
|
|
Type = type,
|
|
Required = _chkRequired.Checked,
|
|
Hint = (_txtHint.Text ?? string.Empty).Trim(),
|
|
DefaultValue = (_txtDefault.Text ?? string.Empty).Trim(),
|
|
Min = (_txtMin.Text ?? string.Empty).Trim(),
|
|
Max = (_txtMax.Text ?? string.Empty).Trim(),
|
|
Group = (_txtGroup.Text ?? string.Empty).Trim(),
|
|
Order = (int)_numOrder.Value,
|
|
EnumOptions = ParseLines(_txtEnumOptions.Text)
|
|
};
|
|
def.Normalize();
|
|
|
|
var err = ValidateDefinition(def);
|
|
if (err != null)
|
|
{
|
|
MessageBox.Show(this, err, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
Result = def;
|
|
DialogResult = DialogResult.OK;
|
|
Close();
|
|
}
|
|
|
|
private static List<string> ParseLines(string text)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(text))
|
|
{
|
|
return new List<string>();
|
|
}
|
|
|
|
return text
|
|
.Replace("\r\n", "\n")
|
|
.Replace("\r", "\n")
|
|
.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)
|
|
.Select(s => (s ?? string.Empty).Trim())
|
|
.Where(s => s.Length > 0)
|
|
.ToList();
|
|
}
|
|
|
|
private static bool IsValidKey(string key)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(key))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!char.IsLetter(key[0]))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
foreach (var ch in key)
|
|
{
|
|
if (char.IsLetterOrDigit(ch) || ch == '_')
|
|
{
|
|
continue;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static string ValidateDefinition(ParamDefinition def)
|
|
{
|
|
if (def == null)
|
|
{
|
|
return "参数定义不能为空。";
|
|
}
|
|
|
|
if (def.Type == ParamValueType.Enum && (def.EnumOptions == null || def.EnumOptions.Count == 0))
|
|
{
|
|
return "Enum 类型必须提供至少 1 个枚举选项。";
|
|
}
|
|
|
|
if ((def.Type == ParamValueType.Int || def.Type == ParamValueType.Double) && (def.Min.Length > 0 || def.Max.Length > 0))
|
|
{
|
|
if (!TryParseDouble(def.Min, out var min, allowEmpty: true))
|
|
{
|
|
return "最小值不是有效数字。";
|
|
}
|
|
|
|
if (!TryParseDouble(def.Max, out var max, allowEmpty: true))
|
|
{
|
|
return "最大值不是有效数字。";
|
|
}
|
|
|
|
if (def.Min.Length > 0 && def.Max.Length > 0 && min > max)
|
|
{
|
|
return "最小值不能大于最大值。";
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static bool TryParseDouble(string text, out double value, bool allowEmpty)
|
|
{
|
|
value = 0;
|
|
if (string.IsNullOrWhiteSpace(text))
|
|
{
|
|
return allowEmpty;
|
|
}
|
|
|
|
var s = text.Trim();
|
|
if (double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return double.TryParse(s, NumberStyles.Float, CultureInfo.CurrentCulture, out value);
|
|
}
|
|
}
|
|
}
|