using System.Drawing;
namespace Shigure;
///
/// 动态单位 / 数量字段的编辑弹窗: 选择类别(单位/数量)与选择器, 按所选类型动态显隐参数控件。
/// 光环候选来自当前职业/专精的 group 字段。校验名称非空、唯一、非纯数字、不含 '.'/'$'。
///
public sealed class UnitEditorForm : Form
{
private const int RowWidth = 800;
private const int LabelWidth = 132;
private const int ControlLeft = LabelWidth + 10;
private static readonly RoleOption[] RoleOptions =
[
new("坦克 (1)", 1),
new("治疗 (2)", 2),
new("输出 (3)", 3)
];
private static readonly DispelTypeOption[] DispelTypeOptions =
[
new("1: 魔法", 1),
new("2: 疾病", 2),
new("3: 诅咒", 3),
new("4: 中毒", 4)
];
private static readonly LowestHealthAuraFilterItem[] LowestHealthAuraFilterOptions =
[
new("不筛选光环", LowestHealthAuraFilterKind.None),
new("带任一光环", LowestHealthAuraFilterKind.WithAnyAura),
new("不带某光环", LowestHealthAuraFilterKind.WithoutAura),
new("带某光环", LowestHealthAuraFilterKind.WithAura),
new("某光环值等于", LowestHealthAuraFilterKind.WithAuraCount)
];
private static readonly SelectorItem[] UnitSelectors =
[
new("生命值最低", UnitSelectorKind.LowestHealth),
new("治疗吸收最高", UnitSelectorKind.HighestHealingAbsorb),
new("按职责", UnitSelectorKind.UnitWithRole),
new("按职责且不带某光环", UnitSelectorKind.UnitWithRoleWithoutAura),
new("带某光环(持续最久)", UnitSelectorKind.UnitWithAura),
new("带某驱散类型", UnitSelectorKind.UnitWithDispelType)
];
private static readonly CountItem[] CountSelectors =
[
new("血量 - 低于阈值", CountKind.UnitsBelowHealth),
new("血量 - 低于阈值不带某光环", CountKind.UnitsWithoutAuraBelowHealth),
new("血量 - 低于阈值带某光环", CountKind.UnitsWithAuraBelowHealth),
new("治疗吸收 - 大于阈值", CountKind.UnitsAboveHealingAbsorb),
new("治疗吸收 - 大于阈值不带某光环", CountKind.UnitsWithoutAuraAboveHealingAbsorb),
new("治疗吸收 - 大于阈值带某光环", CountKind.UnitsWithAuraAboveHealingAbsorb),
new("光环 - 带某光环", CountKind.UnitsWithAura)
];
private static readonly ThresholdModeItem[] ThresholdModeOptions =
[
new("固定阈值", false),
new("动态阈值", true)
];
private readonly IReadOnlyList _auraFields;
private readonly IReadOnlyList _thresholdFields;
private readonly HashSet _takenNames;
private readonly Label _healthNameLabel = new();
private readonly TextBox _nameBox = new();
private readonly TextBox _healthNameBox = new();
private readonly ComboBox _categoryBox = new();
private readonly ComboBox _selectorBox = new();
private readonly ComboBox _lowestHealthAuraFilterBox = new();
private readonly FlowLayoutPanel _paramPanel = new();
private readonly Label _previewLabel = new();
private readonly ToolTip _toolTip = new();
private readonly NumericUpDown _thresholdBox = new();
private readonly ComboBox _thresholdModeBox = new();
private readonly ComboBox _thresholdFieldBox = new();
private readonly ComboBox _roleBox = new();
private readonly CheckBox _reverseBox = new();
private readonly ComboBox _auraBox = new();
private readonly CheckedListBox _aurasBox = new();
private readonly NumericUpDown _auraCountBox = new();
private readonly ComboBox _dispelTypeBox = new();
private Panel _thresholdModeRow = null!;
private Panel _thresholdRow = null!;
private Label _thresholdLabel = null!;
private Panel _thresholdFieldRow = null!;
private Panel _lowestHealthAuraFilterRow = null!;
private Panel _roleRow = null!;
private Panel _reverseRow = null!;
private Panel _auraRow = null!;
private Panel _aurasRow = null!;
private Panel _auraCountRow = null!;
private Panel _dispelRow = null!;
private bool _usesHealingAbsorbThreshold;
public ModuleUnit? ResultUnit { get; private set; }
public ModuleCountField? ResultCount { get; private set; }
public UnitEditorForm(
IReadOnlyList auraFields,
IReadOnlyList thresholdFields,
IReadOnlyCollection takenNames,
ModuleUnit? existingUnit,
ModuleCountField? existingCount)
{
_auraFields = auraFields;
_thresholdFields = thresholdFields;
_takenNames = new HashSet(takenNames, StringComparer.OrdinalIgnoreCase);
InitializeComponent();
Seed(existingUnit, existingCount);
UpdateParamVisibility();
UpdateHealthNameState();
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
UiTheme.ApplyDarkTitleBar(this);
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
_nameBox.Focus();
_nameBox.SelectAll();
}
private void InitializeComponent()
{
Text = "编辑单位";
Font = new Font("Microsoft YaHei UI", 9F, FontStyle.Regular, GraphicsUnit.Point);
BackColor = UiTheme.Background;
ForeColor = UiTheme.Text;
ClientSize = new Size(RowWidth + 36, 534);
FormBorderStyle = FormBorderStyle.FixedDialog;
MaximizeBox = false;
MinimizeBox = false;
ShowInTaskbar = false;
StartPosition = FormStartPosition.CenterParent;
var root = new TableLayoutPanel
{
Dock = DockStyle.Fill,
BackColor = UiTheme.Background,
Padding = new Padding(14, 12, 14, 12),
ColumnCount = 1,
RowCount = 5
};
root.RowStyles.Add(new RowStyle(SizeType.Absolute, 38));
root.RowStyles.Add(new RowStyle(SizeType.Absolute, 38));
root.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
root.RowStyles.Add(new RowStyle(SizeType.Absolute, 26));
root.RowStyles.Add(new RowStyle(SizeType.Absolute, 42));
Controls.Add(root);
UiTheme.StyleComboBox(_categoryBox);
_categoryBox.DropDownWidth = 180;
_categoryBox.Items.AddRange(["单位 (可作目标)", "数量 (仅条件)"]);
_categoryBox.SelectedIndex = 0;
_categoryBox.SelectedIndexChanged += (_, _) =>
{
PopulateSelectors();
UpdateParamVisibility();
UpdateHealthNameState();
};
UiTheme.StyleComboBox(_selectorBox);
_selectorBox.DropDownWidth = 360;
_selectorBox.SelectedIndexChanged += (_, _) =>
{
UpdateParamVisibility();
UpdateHealthNameState();
};
root.Controls.Add(BuildSplitRow("类别", _categoryBox, "选择器", _selectorBox), 0, 0);
root.Controls.Add(BuildNameRow(), 0, 1);
_paramPanel.Dock = DockStyle.Fill;
_paramPanel.BackColor = UiTheme.SurfaceRaised;
_paramPanel.FlowDirection = FlowDirection.TopDown;
_paramPanel.WrapContents = false;
_paramPanel.AutoScroll = true;
_paramPanel.Margin = new Padding(0, 8, 0, 6);
_paramPanel.Padding = new Padding(8, 6, 8, 6);
BuildParamRows();
root.Controls.Add(_paramPanel, 0, 2);
_previewLabel.Dock = DockStyle.Fill;
_previewLabel.ForeColor = UiTheme.Muted;
_previewLabel.TextAlign = ContentAlignment.MiddleLeft;
_previewLabel.AutoEllipsis = true;
_previewLabel.Margin = new Padding(2, 2, 2, 0);
root.Controls.Add(_previewLabel, 0, 3);
root.Controls.Add(BuildActionRow(), 0, 4);
PopulateSelectors();
}
private void BuildParamRows()
{
_thresholdBox.Minimum = 1;
_thresholdBox.Maximum = int.MaxValue;
_thresholdBox.Value = 100;
UiTheme.StyleNumericUpDown(_thresholdBox);
UiTheme.StyleComboBox(_thresholdModeBox);
_thresholdModeBox.DropDownWidth = 160;
_thresholdModeBox.Items.AddRange(ThresholdModeOptions.Cast