CadParamPluging/UI/TemplateSchemaBindingForm.cs
2025-12-17 10:04:08 +08:00

529 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using CadParamPluging.Common;
namespace CadParamPluging.UI
{
public class TemplateSchemaBindingForm : Form
{
private readonly ComboBox _cbProjectType;
private readonly ComboBox _cbDrawingType;
private readonly ComboBox _cbSheetSize;
private readonly ComboBox _cbScale;
private readonly TextBox _txtDisplayName;
private readonly Label _lblTemplateKey;
private readonly ListBox _lbSchemas;
private readonly ListView _lvParams;
private readonly ParamCatalog _catalog;
private TemplateSchemas _schemas;
public TemplateSchemaBindingForm(
System.Collections.Generic.IEnumerable<string> projectTypes,
System.Collections.Generic.IEnumerable<string> drawingTypes,
System.Collections.Generic.IEnumerable<string> sheetSizes,
System.Collections.Generic.IEnumerable<string> scales,
ParamCatalog catalog)
{
Text = "模板参数绑定";
Size = new Size(920, 620);
StartPosition = FormStartPosition.CenterParent;
FormBorderStyle = FormBorderStyle.FixedDialog;
MaximizeBox = false;
MinimizeBox = false;
ShowInTaskbar = false;
_catalog = (catalog ?? ParamCatalog.CreateDefault()).Clone();
_catalog.Normalize();
_schemas = TemplateSchemaStore.Load();
_schemas.Normalize();
var root = new TableLayoutPanel
{
Dock = DockStyle.Fill,
Padding = new Padding(10),
ColumnCount = 2,
RowCount = 2
};
root.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 260));
root.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f));
root.RowStyles.Add(new RowStyle(SizeType.Percent, 100f));
root.RowStyles.Add(new RowStyle(SizeType.AutoSize));
_lbSchemas = new ListBox { Dock = DockStyle.Fill };
_lbSchemas.SelectedIndexChanged += (_, __) => LoadSelectedSchemaToUi();
ReloadSchemaList();
var leftButtons = new FlowLayoutPanel
{
Dock = DockStyle.Bottom,
FlowDirection = FlowDirection.LeftToRight,
AutoSize = true
};
var btnNew = new Button { Text = "新增模板", AutoSize = true };
btnNew.Click += (_, __) => OnNewSchema();
var btnDelete = new Button { Text = "删除模板", AutoSize = true };
btnDelete.Click += (_, __) => OnDeleteSchema();
leftButtons.Controls.Add(btnNew);
leftButtons.Controls.Add(btnDelete);
var leftPanel = new Panel { Dock = DockStyle.Fill };
leftPanel.Controls.Add(_lbSchemas);
leftPanel.Controls.Add(leftButtons);
leftButtons.Dock = DockStyle.Bottom;
var editor = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = 2,
RowCount = 4,
AutoSize = true
};
editor.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
editor.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f));
_cbProjectType = CreateCombo(projectTypes);
_cbDrawingType = CreateCombo(drawingTypes);
_cbSheetSize = CreateCombo(sheetSizes);
_cbScale = CreateCombo(scales);
_cbProjectType.SelectedIndexChanged += (_, __) => UpdateTemplateKeyLabel();
_cbDrawingType.SelectedIndexChanged += (_, __) => UpdateTemplateKeyLabel();
_cbSheetSize.SelectedIndexChanged += (_, __) => UpdateTemplateKeyLabel();
_cbScale.SelectedIndexChanged += (_, __) => UpdateTemplateKeyLabel();
_txtDisplayName = new TextBox { Width = 380 };
_lblTemplateKey = new Label { AutoSize = true, ForeColor = Color.DarkBlue };
var row = 0;
editor.Controls.Add(new Label { Text = "交付状态", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
editor.Controls.Add(_cbProjectType, 1, row++);
editor.Controls.Add(new Label { Text = "工艺方法", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
editor.Controls.Add(_cbDrawingType, 1, row++);
editor.Controls.Add(new Label { Text = "结构特征", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
editor.Controls.Add(_cbSheetSize, 1, row++);
editor.Controls.Add(new Label { Text = "特殊条件", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, row);
editor.Controls.Add(_cbScale, 1, row++);
var topBar = new TableLayoutPanel
{
Dock = DockStyle.Top,
ColumnCount = 2,
RowCount = 2,
AutoSize = true
};
topBar.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
topBar.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f));
topBar.Controls.Add(new Label { Text = "显示名称", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, 0);
topBar.Controls.Add(_txtDisplayName, 1, 0);
topBar.Controls.Add(new Label { Text = "TemplateKey", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, 1);
topBar.Controls.Add(_lblTemplateKey, 1, 1);
_lvParams = new ListView
{
Dock = DockStyle.Fill,
View = View.Details,
FullRowSelect = true,
HideSelection = false,
CheckBoxes = true
};
_lvParams.Columns.Add("Label", 220);
_lvParams.Columns.Add("Key", 160);
var paramsButtonPanel = new FlowLayoutPanel
{
Dock = DockStyle.Top,
FlowDirection = FlowDirection.LeftToRight,
AutoSize = true
};
var btnUp = new Button { Text = "上移", AutoSize = true };
btnUp.Click += (_, __) => MoveSelectedParam(-1);
var btnDown = new Button { Text = "下移", AutoSize = true };
btnDown.Click += (_, __) => MoveSelectedParam(1);
var btnSelectAll = new Button { Text = "全选", AutoSize = true };
btnSelectAll.Click += (_, __) => SetAllChecked(true);
var btnUnselectAll = new Button { Text = "全不选", AutoSize = true };
btnUnselectAll.Click += (_, __) => SetAllChecked(false);
paramsButtonPanel.Controls.Add(btnUp);
paramsButtonPanel.Controls.Add(btnDown);
paramsButtonPanel.Controls.Add(btnSelectAll);
paramsButtonPanel.Controls.Add(btnUnselectAll);
var rightPanel = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = 1,
RowCount = 3
};
rightPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
rightPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
rightPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100f));
rightPanel.Controls.Add(editor, 0, 0);
rightPanel.Controls.Add(topBar, 0, 1);
var paramArea = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = 1,
RowCount = 2
};
paramArea.RowStyles.Add(new RowStyle(SizeType.AutoSize));
paramArea.RowStyles.Add(new RowStyle(SizeType.Percent, 100f));
paramArea.Controls.Add(paramsButtonPanel, 0, 0);
paramArea.Controls.Add(_lvParams, 0, 1);
rightPanel.Controls.Add(paramArea, 0, 2);
var bottomButtons = new FlowLayoutPanel
{
Dock = DockStyle.Fill,
FlowDirection = FlowDirection.RightToLeft,
AutoSize = true
};
var btnClose = new Button { Text = "关闭", DialogResult = DialogResult.Cancel };
var btnSave = new Button { Text = "保存" };
btnSave.Click += (_, __) => OnSave();
bottomButtons.Controls.Add(btnClose);
bottomButtons.Controls.Add(btnSave);
root.Controls.Add(leftPanel, 0, 0);
root.Controls.Add(rightPanel, 1, 0);
root.Controls.Add(bottomButtons, 0, 1);
root.SetColumnSpan(bottomButtons, 2);
Controls.Add(root);
CancelButton = btnClose;
BuildParamListItems();
UpdateTemplateKeyLabel();
if (_lbSchemas.Items.Count > 0)
{
_lbSchemas.SelectedIndex = 0;
}
}
private static ComboBox CreateCombo(System.Collections.Generic.IEnumerable<string> items)
{
var cb = new ComboBox { DropDownStyle = ComboBoxStyle.DropDownList, Width = 220 };
var arr = (items ?? Enumerable.Empty<string>())
.Where(s => !string.IsNullOrWhiteSpace(s))
.Select(s => s.Trim())
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToArray();
if (arr.Length > 0)
{
cb.Items.AddRange(arr);
cb.SelectedIndex = 0;
}
return cb;
}
private void BuildParamListItems()
{
_lvParams.BeginUpdate();
try
{
_lvParams.Items.Clear();
foreach (var p in (_catalog.Items ?? Enumerable.Empty<ParamDefinition>()).OrderBy(x => x.Order))
{
var it = new ListViewItem(new[] { p.Label, p.Key })
{
Tag = p.Key,
Checked = false
};
_lvParams.Items.Add(it);
}
}
finally
{
_lvParams.EndUpdate();
}
}
private void ApplySchemaToParamList(TemplateSchemaDefinition schema)
{
var selectedKeys = (schema?.SelectedParamKeys ?? new List<string>()).ToList();
var keySet = new HashSet<string>(selectedKeys, StringComparer.OrdinalIgnoreCase);
var all = _lvParams.Items.Cast<ListViewItem>().ToList();
var byKey = all.ToDictionary(i => (string)i.Tag, i => i, StringComparer.OrdinalIgnoreCase);
var ordered = new List<ListViewItem>();
foreach (var k in selectedKeys)
{
if (byKey.TryGetValue(k, out var it))
{
ordered.Add(it);
}
}
foreach (var it in all)
{
if (!keySet.Contains((string)it.Tag))
{
ordered.Add(it);
}
}
_lvParams.BeginUpdate();
try
{
_lvParams.Items.Clear();
foreach (var it in ordered)
{
var key = (string)it.Tag;
it.Checked = keySet.Contains(key);
_lvParams.Items.Add(it);
}
}
finally
{
_lvParams.EndUpdate();
}
}
private void ReloadSchemaList()
{
var prev = _lbSchemas.SelectedIndex;
_lbSchemas.Items.Clear();
foreach (var s in (_schemas.Items ?? Enumerable.Empty<TemplateSchemaDefinition>())
.OrderBy(x => x.ProjectType)
.ThenBy(x => x.DrawingType)
.ThenBy(x => x.SheetSize)
.ThenBy(x => x.Scale))
{
_lbSchemas.Items.Add(FormatSchema(s));
}
if (_lbSchemas.Items.Count > 0)
{
_lbSchemas.SelectedIndex = Math.Max(0, Math.Min(prev, _lbSchemas.Items.Count - 1));
}
}
private static string FormatSchema(TemplateSchemaDefinition s)
{
if (s == null)
{
return "(null)";
}
var name = string.IsNullOrWhiteSpace(s.DisplayName) ? "(未命名)" : s.DisplayName;
return $"{name} | {s.ProjectType}/{s.DrawingType}/{s.SheetSize}/{s.Scale}";
}
private TemplateSchemaDefinition GetSelectedSchema()
{
var idx = _lbSchemas.SelectedIndex;
if (idx < 0)
{
return null;
}
var ordered = (_schemas.Items ?? Enumerable.Empty<TemplateSchemaDefinition>())
.OrderBy(x => x.ProjectType)
.ThenBy(x => x.DrawingType)
.ThenBy(x => x.SheetSize)
.ThenBy(x => x.Scale)
.ToList();
if (idx >= ordered.Count)
{
return null;
}
var key = ordered[idx].TemplateKey;
return (_schemas.Items ?? new List<TemplateSchemaDefinition>()).FirstOrDefault(x => string.Equals(x.TemplateKey, key, StringComparison.OrdinalIgnoreCase));
}
private void LoadSelectedSchemaToUi()
{
var schema = GetSelectedSchema();
if (schema == null)
{
return;
}
SelectComboByText(_cbProjectType, schema.ProjectType);
SelectComboByText(_cbDrawingType, schema.DrawingType);
SelectComboByText(_cbSheetSize, schema.SheetSize);
SelectComboByText(_cbScale, schema.Scale);
_txtDisplayName.Text = schema.DisplayName ?? string.Empty;
UpdateTemplateKeyLabel();
ApplySchemaToParamList(schema);
}
private static void SelectComboByText(ComboBox cb, string value)
{
if (cb == null)
{
return;
}
var v = (value ?? string.Empty).Trim();
for (var i = 0; i < cb.Items.Count; i++)
{
if (string.Equals((cb.Items[i] as string) ?? string.Empty, v, StringComparison.OrdinalIgnoreCase))
{
cb.SelectedIndex = i;
return;
}
}
}
private void UpdateTemplateKeyLabel()
{
var key = TemplateKeyBuilder.Build(_cbProjectType.Text, _cbDrawingType.Text, _cbSheetSize.Text, _cbScale.Text);
_lblTemplateKey.Text = key ?? string.Empty;
}
private void OnNewSchema()
{
if (string.IsNullOrWhiteSpace(_cbProjectType.Text) || string.IsNullOrWhiteSpace(_cbDrawingType.Text))
{
MessageBox.Show(this, "请先选择模板四个参数。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
var candidate = new TemplateSchemaDefinition
{
ProjectType = _cbProjectType.Text,
DrawingType = _cbDrawingType.Text,
SheetSize = _cbSheetSize.Text,
Scale = _cbScale.Text,
DisplayName = _txtDisplayName.Text
};
candidate.Normalize();
if ((_schemas.Items ?? new List<TemplateSchemaDefinition>()).Any(x => string.Equals(x.TemplateKey, candidate.TemplateKey, StringComparison.OrdinalIgnoreCase)))
{
MessageBox.Show(this, "该模板定义已存在(四参数组合重复)。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (_schemas.Items == null)
{
_schemas.Items = new List<TemplateSchemaDefinition>();
}
_schemas.Items.Add(candidate);
_schemas.Normalize();
ReloadSchemaList();
}
private void OnDeleteSchema()
{
var schema = GetSelectedSchema();
if (schema == null)
{
MessageBox.Show(this, "请先选择一个模板定义。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var confirm = MessageBox.Show(this, $"确认删除模板定义:{FormatSchema(schema)}", "删除", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (confirm != DialogResult.Yes)
{
return;
}
_schemas.Items = (_schemas.Items ?? Enumerable.Empty<TemplateSchemaDefinition>())
.Where(x => !string.Equals(x.TemplateKey, schema.TemplateKey, StringComparison.OrdinalIgnoreCase))
.ToList();
_schemas.Normalize();
ReloadSchemaList();
}
private void MoveSelectedParam(int delta)
{
if (_lvParams.SelectedItems.Count == 0)
{
return;
}
var item = _lvParams.SelectedItems[0];
var idx = item.Index;
var newIdx = idx + delta;
if (newIdx < 0 || newIdx >= _lvParams.Items.Count)
{
return;
}
_lvParams.BeginUpdate();
try
{
_lvParams.Items.RemoveAt(idx);
_lvParams.Items.Insert(newIdx, item);
item.Selected = true;
item.Focused = true;
}
finally
{
_lvParams.EndUpdate();
}
}
private void SetAllChecked(bool value)
{
_lvParams.BeginUpdate();
try
{
foreach (ListViewItem it in _lvParams.Items)
{
it.Checked = value;
}
}
finally
{
_lvParams.EndUpdate();
}
}
private void OnSave()
{
var schema = GetSelectedSchema();
if (schema == null)
{
MessageBox.Show(this, "请先选择一个模板定义。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
schema.ProjectType = _cbProjectType.Text;
schema.DrawingType = _cbDrawingType.Text;
schema.SheetSize = _cbSheetSize.Text;
schema.Scale = _cbScale.Text;
schema.DisplayName = _txtDisplayName.Text;
schema.SelectedParamKeys = _lvParams.Items
.Cast<ListViewItem>()
.Where(i => i.Checked)
.Select(i => (string)i.Tag)
.ToList();
schema.Normalize();
if ((_schemas.Items ?? new List<TemplateSchemaDefinition>())
.Any(x => !ReferenceEquals(x, schema) && string.Equals(x.TemplateKey, schema.TemplateKey, StringComparison.OrdinalIgnoreCase)))
{
MessageBox.Show(this, "保存失败:存在重复的四参数组合。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
try
{
TemplateSchemaStore.Save(_schemas);
MessageBox.Show(this, "已保存。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
ReloadSchemaList();
}
catch (Exception ex)
{
MessageBox.Show(this, $"保存失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}