From 69ef76e16eaab69128b3ccf9e00c31b13910be21 Mon Sep 17 00:00:00 2001 From: sladro Date: Mon, 13 Apr 2026 13:38:54 +0800 Subject: [PATCH] Support editable dropdown display names --- Common/DropdownOptions.cs | 184 ++++++++++++++++++- Tests/DropdownDisplayNameTests.cs | 51 ++++++ UI/DrawingParamsForm.cs | 15 +- UI/ParamDrawingPanel.cs | 46 ++--- UI/SettingsForm.cs | 288 ++++++++++++++++++++---------- UI/TemplateSchemaBindingForm.cs | 92 +++++++--- 6 files changed, 522 insertions(+), 154 deletions(-) create mode 100644 Tests/DropdownDisplayNameTests.cs diff --git a/Common/DropdownOptions.cs b/Common/DropdownOptions.cs index 4114df1..c224452 100644 --- a/Common/DropdownOptions.cs +++ b/Common/DropdownOptions.cs @@ -1,14 +1,32 @@ using System; using System.Collections.Generic; +using System.Linq; namespace CadParamPluging.Common { + [Serializable] + public class DropdownDisplayNameOverride + { + public string Category { get; set; } + public string Value { get; set; } + public string DisplayName { get; set; } + } + + public static class DropdownOptionCategory + { + public const string DeliveryStatus = "DeliveryStatus"; + public const string ProcessMethod = "ProcessMethod"; + public const string StructuralFeature = "StructuralFeature"; + public const string SpecialCondition = "SpecialCondition"; + } + public class DropdownOptions { public List DeliveryStatuses { get; set; } public List ProcessMethods { get; set; } public List StructuralFeatures { get; set; } public List SpecialConditions { get; set; } + public List DisplayNameOverrides { get; set; } public DropdownOptions() @@ -17,6 +35,7 @@ namespace CadParamPluging.Common ProcessMethods = new List(); StructuralFeatures = new List(); SpecialConditions = new List(); + DisplayNameOverrides = new List(); } public static DropdownOptions CreateDefault() @@ -37,7 +56,16 @@ namespace CadParamPluging.Common DeliveryStatuses = new List(DeliveryStatuses ?? new List()), ProcessMethods = new List(ProcessMethods ?? new List()), StructuralFeatures = new List(StructuralFeatures ?? new List()), - SpecialConditions = new List(SpecialConditions ?? new List()) + SpecialConditions = new List(SpecialConditions ?? new List()), + DisplayNameOverrides = (DisplayNameOverrides ?? new List()) + .Where(x => x != null) + .Select(x => new DropdownDisplayNameOverride + { + Category = x.Category, + Value = x.Value, + DisplayName = x.DisplayName + }) + .ToList() }; } @@ -47,6 +75,79 @@ namespace CadParamPluging.Common ProcessMethods = NormalizeList(ProcessMethods); StructuralFeatures = NormalizeList(StructuralFeatures); SpecialConditions = NormalizeList(SpecialConditions); + DisplayNameOverrides = NormalizeOverrides(DisplayNameOverrides); + } + + public string GetDisplayName(string category, string rawValue) + { + var raw = (rawValue ?? string.Empty).Trim(); + if (raw.Length == 0) + { + return string.Empty; + } + + var normalizedCategory = NormalizeCategory(category); + var match = (DisplayNameOverrides ?? new List()) + .FirstOrDefault(x => + x != null + && string.Equals(NormalizeCategory(x.Category), normalizedCategory, StringComparison.OrdinalIgnoreCase) + && string.Equals((x.Value ?? string.Empty).Trim(), raw, StringComparison.OrdinalIgnoreCase)); + + var display = (match != null ? match.DisplayName : null) ?? raw; + display = display.Trim(); + return display.Length == 0 ? raw : display; + } + + public void SetDisplayNameOverride(string category, string rawValue, string displayName) + { + var normalizedCategory = NormalizeCategory(category); + var raw = (rawValue ?? string.Empty).Trim(); + var display = (displayName ?? string.Empty).Trim(); + if (raw.Length == 0) + { + return; + } + + if (DisplayNameOverrides == null) + { + DisplayNameOverrides = new List(); + } + + DisplayNameOverrides = (DisplayNameOverrides ?? new List()) + .Where(x => + x != null + && (!string.Equals(NormalizeCategory(x.Category), normalizedCategory, StringComparison.OrdinalIgnoreCase) + || !string.Equals((x.Value ?? string.Empty).Trim(), raw, StringComparison.OrdinalIgnoreCase))) + .ToList(); + + if (display.Length == 0 || string.Equals(display, raw, StringComparison.OrdinalIgnoreCase)) + { + return; + } + + DisplayNameOverrides.Add(new DropdownDisplayNameOverride + { + Category = normalizedCategory, + Value = raw, + DisplayName = display + }); + } + + public List GetValues(string category) + { + switch (NormalizeCategory(category)) + { + case DropdownOptionCategory.DeliveryStatus: + return DeliveryStatuses; + case DropdownOptionCategory.ProcessMethod: + return ProcessMethods; + case DropdownOptionCategory.StructuralFeature: + return StructuralFeatures; + case DropdownOptionCategory.SpecialCondition: + return SpecialConditions; + default: + return new List(); + } } private static List NormalizeList(IEnumerable values) @@ -74,5 +175,86 @@ namespace CadParamPluging.Common return result; } + + private static List NormalizeOverrides(IEnumerable values) + { + var result = new List(); + if (values == null) + { + return result; + } + + var seen = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var raw in values) + { + if (raw == null) + { + continue; + } + + var category = NormalizeCategory(raw.Category); + var value = (raw.Value ?? string.Empty).Trim(); + var display = (raw.DisplayName ?? string.Empty).Trim(); + if (category.Length == 0 || value.Length == 0 || display.Length == 0) + { + continue; + } + + if (string.Equals(value, display, StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + var key = category + "|" + value; + if (!seen.Add(key)) + { + continue; + } + + result.Add(new DropdownDisplayNameOverride + { + Category = category, + Value = value, + DisplayName = display + }); + } + + return result; + } + + private static string NormalizeCategory(string category) + { + var value = (category ?? string.Empty).Trim(); + if (value.Length == 0) + { + return string.Empty; + } + + if (string.Equals(value, DropdownOptionCategory.DeliveryStatus, StringComparison.OrdinalIgnoreCase) + || string.Equals(value, "DeliveryStatuses", StringComparison.OrdinalIgnoreCase)) + { + return DropdownOptionCategory.DeliveryStatus; + } + + if (string.Equals(value, DropdownOptionCategory.ProcessMethod, StringComparison.OrdinalIgnoreCase) + || string.Equals(value, "ProcessMethods", StringComparison.OrdinalIgnoreCase)) + { + return DropdownOptionCategory.ProcessMethod; + } + + if (string.Equals(value, DropdownOptionCategory.StructuralFeature, StringComparison.OrdinalIgnoreCase) + || string.Equals(value, "StructuralFeatures", StringComparison.OrdinalIgnoreCase)) + { + return DropdownOptionCategory.StructuralFeature; + } + + if (string.Equals(value, DropdownOptionCategory.SpecialCondition, StringComparison.OrdinalIgnoreCase) + || string.Equals(value, "SpecialConditions", StringComparison.OrdinalIgnoreCase)) + { + return DropdownOptionCategory.SpecialCondition; + } + + return value; + } } } diff --git a/Tests/DropdownDisplayNameTests.cs b/Tests/DropdownDisplayNameTests.cs new file mode 100644 index 0000000..6a64974 --- /dev/null +++ b/Tests/DropdownDisplayNameTests.cs @@ -0,0 +1,51 @@ +using System; +using CadParamPluging.Common; + +public static class DropdownDisplayNameTests +{ + public static int Main() + { + try + { + KeepsInternalValueWhenRenamingDisplayName(); + RemovesRedundantOverrideWhenDisplayMatchesRawValue(); + Console.WriteLine("All dropdown display-name tests passed."); + return 0; + } + catch (Exception ex) + { + Console.Error.WriteLine(ex.Message); + return 1; + } + } + + private static void KeepsInternalValueWhenRenamingDisplayName() + { + var options = DropdownOptions.CreateDefault(); + + options.SetDisplayNameOverride(DropdownOptionCategory.DeliveryStatus, "车加工", "粗加工"); + + AssertEqual("车加工", options.DeliveryStatuses[1], "Internal value must stay canonical."); + AssertEqual("粗加工", options.GetDisplayName(DropdownOptionCategory.DeliveryStatus, "车加工"), "Display name override should be used."); + } + + private static void RemovesRedundantOverrideWhenDisplayMatchesRawValue() + { + var options = DropdownOptions.CreateDefault(); + + options.SetDisplayNameOverride(DropdownOptionCategory.DeliveryStatus, "车加工", "粗加工"); + options.SetDisplayNameOverride(DropdownOptionCategory.DeliveryStatus, "车加工", "车加工"); + options.Normalize(); + + AssertEqual("车加工", options.GetDisplayName(DropdownOptionCategory.DeliveryStatus, "车加工"), "Default display should fall back to raw value."); + AssertEqual(0, options.DisplayNameOverrides.Count, "Redundant override should be removed."); + } + + private static void AssertEqual(T expected, T actual, string message) + { + if (!object.Equals(expected, actual)) + { + throw new InvalidOperationException(message + " Expected: " + expected + "; Actual: " + actual); + } + } +} diff --git a/UI/DrawingParamsForm.cs b/UI/DrawingParamsForm.cs index 7ec2320..026bf24 100644 --- a/UI/DrawingParamsForm.cs +++ b/UI/DrawingParamsForm.cs @@ -18,6 +18,7 @@ namespace CadParamPluging.UI private readonly Dictionary _defsByControlKey; private readonly ParamCatalog _catalog; private readonly TemplateSchemaDefinition _schema; + private readonly DropdownOptions _dropdownOptions; private readonly ToolTip _toolTip; private readonly TabControl _notePreviewTabs; @@ -37,12 +38,14 @@ namespace CadParamPluging.UI public ParamBag Result { get; private set; } private ParamBag _loadedDefaults; // 新增:外部传入的默认值 - public DrawingParamsForm(ParamCatalog catalog, TemplateSchemaDefinition schema, ParamBag loadedDefaults = null) + public DrawingParamsForm(ParamCatalog catalog, TemplateSchemaDefinition schema, ParamBag loadedDefaults = null, DropdownOptions dropdownOptions = null) { _catalog = (catalog ?? ParamCatalog.CreateDefault()).Clone(); _catalog.Normalize(); _schema = schema; _loadedDefaults = loadedDefaults; // 存储传入的默认值 + _dropdownOptions = (dropdownOptions ?? DropdownOptions.CreateDefault()).Clone(); + _dropdownOptions.Normalize(); Text = "填写参数"; Size = new Size(980, 680); @@ -193,7 +196,7 @@ namespace CadParamPluging.UI } } - private static string BuildHeaderText(TemplateSchemaDefinition schema) + private string BuildHeaderText(TemplateSchemaDefinition schema) { if (schema == null) { @@ -201,7 +204,13 @@ namespace CadParamPluging.UI } var name = string.IsNullOrWhiteSpace(schema.DisplayName) ? "(未命名模板)" : schema.DisplayName; - return $"模板: {name} | {schema.ProjectType}/{schema.DrawingType}/{schema.SheetSize}/{schema.Scale}"; + return string.Format( + "模板: {0} | {1}/{2}/{3}/{4}", + name, + _dropdownOptions.GetDisplayName(DropdownOptionCategory.DeliveryStatus, schema.ProjectType), + _dropdownOptions.GetDisplayName(DropdownOptionCategory.ProcessMethod, schema.DrawingType), + _dropdownOptions.GetDisplayName(DropdownOptionCategory.StructuralFeature, schema.SheetSize), + _dropdownOptions.GetDisplayName(DropdownOptionCategory.SpecialCondition, schema.Scale)); } private void BuildFields() diff --git a/UI/ParamDrawingPanel.cs b/UI/ParamDrawingPanel.cs index e830123..0424948 100644 --- a/UI/ParamDrawingPanel.cs +++ b/UI/ParamDrawingPanel.cs @@ -21,6 +21,7 @@ namespace CadParamPluging.UI private readonly ComboBox _cbDrawingType; private readonly ComboBox _cbSheetSize; private readonly ComboBox _cbScale; + private DropdownOptions _dropdownOptions; private TextBox _txtLog; @@ -28,7 +29,7 @@ namespace CadParamPluging.UI { Dock = DockStyle.Fill; - var dropdownOptions = DropdownOptionsStore.Load(); + _dropdownOptions = DropdownOptionsStore.Load(); var layout = new TableLayoutPanel { @@ -40,10 +41,10 @@ namespace CadParamPluging.UI Padding = new Padding(8) }; - _cbProjectType = CreateComboBox(dropdownOptions.DeliveryStatuses); - _cbDrawingType = CreateComboBox(dropdownOptions.ProcessMethods); - _cbSheetSize = CreateComboBox(dropdownOptions.StructuralFeatures); - _cbScale = CreateComboBox(dropdownOptions.SpecialConditions); + _cbProjectType = CreateComboBox(_dropdownOptions.DeliveryStatuses, _dropdownOptions, DropdownOptionCategory.DeliveryStatus); + _cbDrawingType = CreateComboBox(_dropdownOptions.ProcessMethods, _dropdownOptions, DropdownOptionCategory.ProcessMethod); + _cbSheetSize = CreateComboBox(_dropdownOptions.StructuralFeatures, _dropdownOptions, DropdownOptionCategory.StructuralFeature); + _cbScale = CreateComboBox(_dropdownOptions.SpecialConditions, _dropdownOptions, DropdownOptionCategory.SpecialCondition); // Initialize template controls here in constructor to follow readonly/non-readonly best practices, // though they are no longer readonly. @@ -239,7 +240,7 @@ namespace CadParamPluging.UI var catalog = ParamCatalogStore.Load(); CadParamPluging.Common.ParamBag bag; // 若用户点击了【读取参数】,则将读取到的参数作为本次弹窗的默认值回填 - using (var f = new DrawingParamsForm(catalog, schema, _lastLoadedBag)) + using (var f = new DrawingParamsForm(catalog, schema, _lastLoadedBag, _dropdownOptions)) { var r = f.ShowDialog(this); if (r != DialogResult.OK) @@ -626,6 +627,7 @@ namespace CadParamPluging.UI if (form.ShowDialog() == DialogResult.OK) { DropdownOptionsStore.Save(form.Result); + _dropdownOptions = form.Result.Clone(); ReloadDropdownOptions(form.Result); AppendLog("设置已保存"); } @@ -750,10 +752,10 @@ namespace CadParamPluging.UI return; } - ResetComboBoxItems(_cbProjectType, options.DeliveryStatuses); - ResetComboBoxItems(_cbDrawingType, options.ProcessMethods); - ResetComboBoxItems(_cbSheetSize, options.StructuralFeatures); - ResetComboBoxItems(_cbScale, options.SpecialConditions); + ResetComboBoxItems(_cbProjectType, options.DeliveryStatuses, options, DropdownOptionCategory.DeliveryStatus); + ResetComboBoxItems(_cbDrawingType, options.ProcessMethods, options, DropdownOptionCategory.ProcessMethod); + ResetComboBoxItems(_cbSheetSize, options.StructuralFeatures, options, DropdownOptionCategory.StructuralFeature); + ResetComboBoxItems(_cbScale, options.SpecialConditions, options, DropdownOptionCategory.SpecialCondition); } private TemplateParams CollectTemplateParams() @@ -789,7 +791,7 @@ namespace CadParamPluging.UI return cb.Text?.Trim(); } - private static ComboBox CreateComboBox(System.Collections.Generic.IEnumerable items) + private static ComboBox CreateComboBox(System.Collections.Generic.IEnumerable items, DropdownOptions options, string category) { var cb = new ComboBox { @@ -825,11 +827,11 @@ namespace CadParamPluging.UI cb.Tag = -1; }; - ResetComboBoxItems(cb, items); + ResetComboBoxItems(cb, items, options, category); return cb; } - private static void ResetComboBoxItems(ComboBox cb, System.Collections.Generic.IEnumerable items) + private static void ResetComboBoxItems(ComboBox cb, System.Collections.Generic.IEnumerable items, DropdownOptions options, string category) { if (cb == null) { @@ -848,23 +850,7 @@ namespace CadParamPluging.UI var dropDownItems = new System.Collections.Generic.List(); foreach (var item in arr) { - string display = item; - if (item == "中心冲孔") - { - display = "无扩孔"; - } - else if (item == "非中心冲孔" || item == "非中心冲孔有扩孔") - { - display = "有扩孔"; - } - else if (item == "车加工") - { - display = "粗加工"; - } - else if (item == "毛料态") - { - display = "非粗加工"; - } + var display = options != null ? options.GetDisplayName(category, item) : item; dropDownItems.Add(new DropdownItem { Display = display, Value = item }); } cb.Items.AddRange(dropDownItems.ToArray()); diff --git a/UI/SettingsForm.cs b/UI/SettingsForm.cs index 873d731..4122b48 100644 --- a/UI/SettingsForm.cs +++ b/UI/SettingsForm.cs @@ -1,6 +1,6 @@ using System; +using System.Collections.Generic; using System.Drawing; -using System.IO; using System.Linq; using System.Windows.Forms; using CadParamPluging.Common; @@ -9,11 +9,25 @@ namespace CadParamPluging.UI { public class SettingsForm : Form { + private sealed class EditableOptionItem + { + public string Category { get; set; } + public string RawValue { get; set; } + public string DisplayName { get; set; } + public bool IsBuiltIn { get; set; } + + public override string ToString() + { + return DisplayName; + } + } + private readonly ListBox _lbDeliveryStatuses; private readonly ListBox _lbProcessMethods; private readonly ListBox _lbStructuralFeatures; private readonly ListBox _lbSpecialConditions; - + private readonly DropdownOptions _workingOptions; + private readonly DropdownOptions _builtInDefaults; public DropdownOptions Result { get; private set; } @@ -26,7 +40,12 @@ namespace CadParamPluging.UI MaximizeBox = false; MinimizeBox = false; ShowInTaskbar = false; - Font = SystemFonts.MessageBoxFont; // Use system font for consistent look + Font = SystemFonts.MessageBoxFont; + + _workingOptions = (current ?? DropdownOptions.CreateDefault()).Clone(); + _workingOptions.Normalize(); + _builtInDefaults = DropdownOptions.CreateDefault(); + _builtInDefaults.Normalize(); var mainLayout = new TableLayoutPanel { @@ -35,60 +54,51 @@ namespace CadParamPluging.UI RowCount = 2, ColumnCount = 1 }; - mainLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 100f)); // Tabs - mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // Buttons + mainLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 100f)); + mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); _lbDeliveryStatuses = new ListBox(); _lbProcessMethods = new ListBox(); _lbStructuralFeatures = new ListBox(); _lbSpecialConditions = new ListBox(); - var options = (current ?? DropdownOptions.CreateDefault()).Clone(); - options.Normalize(); + RefreshList(_lbDeliveryStatuses, DropdownOptionCategory.DeliveryStatus); + RefreshList(_lbProcessMethods, DropdownOptionCategory.ProcessMethod); + RefreshList(_lbStructuralFeatures, DropdownOptionCategory.StructuralFeature); + RefreshList(_lbSpecialConditions, DropdownOptionCategory.SpecialCondition); - FillList(_lbDeliveryStatuses, options.DeliveryStatuses); - FillList(_lbProcessMethods, options.ProcessMethods); - FillList(_lbStructuralFeatures, options.StructuralFeatures); - FillList(_lbSpecialConditions, options.SpecialConditions); - - - - // 2. Tabs Section var tabs = new TabControl { Dock = DockStyle.Fill }; tabs.TabPages.Add(BuildEditableTab("交付状态", _lbDeliveryStatuses)); tabs.TabPages.Add(BuildEditableTab("工艺方法", _lbProcessMethods)); tabs.TabPages.Add(BuildEditableTab("结构特征", _lbStructuralFeatures)); tabs.TabPages.Add(BuildEditableTab("特殊条件", _lbSpecialConditions)); - // 3. Bottom Section (Separated into Left (Tools) and Right (Dialog)) - var bottomGrid = new TableLayoutPanel - { - Dock = DockStyle.Fill, - RowCount = 1, - ColumnCount = 2, + var bottomGrid = new TableLayoutPanel + { + Dock = DockStyle.Fill, + RowCount = 1, + ColumnCount = 2, AutoSize = true, - Margin = new Padding(0, 8, 0, 0) // Top margin for spacing + Margin = new Padding(0, 8, 0, 0) }; bottomGrid.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f)); bottomGrid.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); - // Left tools - var leftTools = new FlowLayoutPanel - { - Dock = DockStyle.Fill, - AutoSize = true, - FlowDirection = FlowDirection.LeftToRight + var leftTools = new FlowLayoutPanel + { + Dock = DockStyle.Fill, + AutoSize = true, + FlowDirection = FlowDirection.LeftToRight }; var btnParamCatalog = new Button { Text = "参数总表", AutoSize = true }; btnParamCatalog.Click += (_, __) => OnOpenParamCatalog(); - + var btnTemplateBinding = new Button { Text = "模板绑定", AutoSize = true }; btnTemplateBinding.Click += (_, __) => OnOpenTemplateBinding(); leftTools.Controls.Add(btnParamCatalog); leftTools.Controls.Add(btnTemplateBinding); - // Right actions var rightActions = new FlowLayoutPanel { Dock = DockStyle.Fill, @@ -99,13 +109,12 @@ namespace CadParamPluging.UI var btnOk = new Button { Text = "确定", Width = 80 }; btnOk.Click += (_, __) => OnOk(); - rightActions.Controls.Add(btnCancel); // Add in reverse order due to RightToLeft flow + rightActions.Controls.Add(btnCancel); rightActions.Controls.Add(btnOk); bottomGrid.Controls.Add(leftTools, 0, 0); bottomGrid.Controls.Add(rightActions, 1, 0); - // Assemble Main mainLayout.Controls.Add(tabs, 0, 0); mainLayout.Controls.Add(bottomGrid, 0, 1); @@ -115,8 +124,6 @@ namespace CadParamPluging.UI CancelButton = btnCancel; } - - private void OnOpenParamCatalog() { try @@ -129,7 +136,7 @@ namespace CadParamPluging.UI } catch (Exception ex) { - MessageBox.Show(this, $"打开参数总表失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + MessageBox.Show(this, "打开参数总表失败: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } @@ -138,42 +145,14 @@ namespace CadParamPluging.UI try { var catalog = ParamCatalogStore.Load(); - - var projectTypes = _lbDeliveryStatuses.Items.Cast().Select(o => (o as string) ?? string.Empty).ToList(); - var drawingTypes = _lbProcessMethods.Items.Cast().Select(o => (o as string) ?? string.Empty).ToList(); - var sheetSizes = _lbStructuralFeatures.Items.Cast().Select(o => (o as string) ?? string.Empty).ToList(); - var scales = _lbSpecialConditions.Items.Cast().Select(o => (o as string) ?? string.Empty).ToList(); - - using (var f = new TemplateSchemaBindingForm(projectTypes, drawingTypes, sheetSizes, scales, catalog)) + using (var f = new TemplateSchemaBindingForm(_workingOptions.Clone(), catalog)) { f.ShowDialog(this); } } catch (Exception ex) { - MessageBox.Show(this, $"打开模板参数绑定失败:\n\n{ex}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - private static void FillList(ListBox listBox, System.Collections.Generic.IEnumerable items) - { - listBox.Items.Clear(); - if (items == null) - { - return; - } - - foreach (var item in items) - { - if (!string.IsNullOrWhiteSpace(item)) - { - listBox.Items.Add(item.Trim()); - } - } - - if (listBox.Items.Count > 0) - { - listBox.SelectedIndex = 0; + MessageBox.Show(this, "打开模板参数绑定失败:\n\n" + ex, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } @@ -190,10 +169,10 @@ namespace CadParamPluging.UI RowCount = 1, }; layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f)); - layout.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100f)); // Fixed width for button column + layout.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100f)); listBox.Dock = DockStyle.Fill; - listBox.IntegralHeight = false; // smoother resizing + listBox.IntegralHeight = false; var actions = new FlowLayoutPanel { @@ -222,9 +201,10 @@ namespace CadParamPluging.UI return page; } - private void OnAddItem(string category, ListBox listBox) + private void OnAddItem(string categoryTitle, ListBox listBox) { - if (!TextInputForm.TryGetValue(this, $"{category} - 新增", "请输入内容:", string.Empty, out var value)) + var category = GetCategoryKey(categoryTitle); + if (!TextInputForm.TryGetValue(this, categoryTitle + " - 新增", "请输入内容:", string.Empty, out var value)) { return; } @@ -236,20 +216,28 @@ namespace CadParamPluging.UI return; } - listBox.Items.Add(value); - listBox.SelectedIndex = listBox.Items.Count - 1; + var list = GetOptionList(category); + if (list.Any(x => string.Equals(x, value, StringComparison.OrdinalIgnoreCase))) + { + MessageBox.Show(this, "该项已存在。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + list.Add(value); + RefreshList(listBox, category, value); } - private void OnEditItem(string category, ListBox listBox) + private void OnEditItem(string categoryTitle, ListBox listBox) { - var selected = listBox.SelectedItem as string; - if (string.IsNullOrWhiteSpace(selected)) + var item = listBox.SelectedItem as EditableOptionItem; + if (item == null || string.IsNullOrWhiteSpace(item.RawValue)) { MessageBox.Show(this, "请先选择一项再修改。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } - if (!TextInputForm.TryGetValue(this, $"{category} - 修改", "请输入内容:", selected, out var value)) + var prompt = item.IsBuiltIn ? "请输入显示名称:" : "请输入内容:"; + if (!TextInputForm.TryGetValue(this, categoryTitle + " - 修改", prompt, item.DisplayName, out var value)) { return; } @@ -261,24 +249,52 @@ namespace CadParamPluging.UI return; } - var idx = listBox.SelectedIndex; - listBox.Items[idx] = value; - listBox.SelectedIndex = idx; + if (item.IsBuiltIn) + { + _workingOptions.SetDisplayNameOverride(item.Category, item.RawValue, value); + RefreshList(listBox, item.Category, item.RawValue); + return; + } + + var list = GetOptionList(item.Category); + var duplicate = list.Any(x => !string.Equals(x, item.RawValue, StringComparison.OrdinalIgnoreCase) + && string.Equals(x, value, StringComparison.OrdinalIgnoreCase)); + if (duplicate) + { + MessageBox.Show(this, "该项已存在。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + var idx = list.FindIndex(x => string.Equals(x, item.RawValue, StringComparison.OrdinalIgnoreCase)); + if (idx < 0) + { + return; + } + + _workingOptions.SetDisplayNameOverride(item.Category, item.RawValue, item.RawValue); + list[idx] = value; + RefreshList(listBox, item.Category, value); } - private void OnDeleteItem(string category, ListBox listBox) + private void OnDeleteItem(string categoryTitle, ListBox listBox) { - var selected = listBox.SelectedItem as string; - if (string.IsNullOrWhiteSpace(selected)) + var item = listBox.SelectedItem as EditableOptionItem; + if (item == null || string.IsNullOrWhiteSpace(item.RawValue)) { MessageBox.Show(this, "请先选择一项再删除。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } + if (item.IsBuiltIn) + { + MessageBox.Show(this, "内置项不建议删除。如需换名字,请使用【修改】。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + var confirm = MessageBox.Show( this, - $"确认删除:{selected}?", - $"{category} - 删除", + "确认删除:" + item.DisplayName + "?", + categoryTitle + " - 删除", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); @@ -287,24 +303,15 @@ namespace CadParamPluging.UI return; } - var idx = listBox.SelectedIndex; - listBox.Items.RemoveAt(idx); - if (listBox.Items.Count > 0) - { - listBox.SelectedIndex = Math.Min(idx, listBox.Items.Count - 1); - } + var list = GetOptionList(item.Category); + list.RemoveAll(x => string.Equals(x, item.RawValue, StringComparison.OrdinalIgnoreCase)); + _workingOptions.SetDisplayNameOverride(item.Category, item.RawValue, item.RawValue); + RefreshList(listBox, item.Category, null); } private void OnOk() { - var result = new DropdownOptions - { - DeliveryStatuses = _lbDeliveryStatuses.Items.Cast().Select(o => (o as string) ?? string.Empty).ToList(), - ProcessMethods = _lbProcessMethods.Items.Cast().Select(o => (o as string) ?? string.Empty).ToList(), - StructuralFeatures = _lbStructuralFeatures.Items.Cast().Select(o => (o as string) ?? string.Empty).ToList(), - SpecialConditions = _lbSpecialConditions.Items.Cast().Select(o => (o as string) ?? string.Empty).ToList() - }; - + var result = _workingOptions.Clone(); result.Normalize(); var err = ValidateResult(result); @@ -319,6 +326,93 @@ namespace CadParamPluging.UI Close(); } + private void RefreshList(ListBox listBox, string category, string preferredRawValue = null) + { + listBox.Items.Clear(); + + foreach (var rawValue in GetOptionList(category)) + { + listBox.Items.Add(new EditableOptionItem + { + Category = category, + RawValue = rawValue, + DisplayName = _workingOptions.GetDisplayName(category, rawValue), + IsBuiltIn = GetBuiltInValues(category).Any(x => string.Equals(x, rawValue, StringComparison.OrdinalIgnoreCase)) + }); + } + + if (listBox.Items.Count == 0) + { + return; + } + + if (!string.IsNullOrWhiteSpace(preferredRawValue)) + { + for (var i = 0; i < listBox.Items.Count; i++) + { + var item = listBox.Items[i] as EditableOptionItem; + if (item != null && string.Equals(item.RawValue, preferredRawValue, StringComparison.OrdinalIgnoreCase)) + { + listBox.SelectedIndex = i; + return; + } + } + } + + listBox.SelectedIndex = 0; + } + + private List GetOptionList(string category) + { + switch (category) + { + case DropdownOptionCategory.DeliveryStatus: + return _workingOptions.DeliveryStatuses; + case DropdownOptionCategory.ProcessMethod: + return _workingOptions.ProcessMethods; + case DropdownOptionCategory.StructuralFeature: + return _workingOptions.StructuralFeatures; + case DropdownOptionCategory.SpecialCondition: + return _workingOptions.SpecialConditions; + default: + return new List(); + } + } + + private List GetBuiltInValues(string category) + { + switch (category) + { + case DropdownOptionCategory.DeliveryStatus: + return _builtInDefaults.DeliveryStatuses; + case DropdownOptionCategory.ProcessMethod: + return _builtInDefaults.ProcessMethods; + case DropdownOptionCategory.StructuralFeature: + return _builtInDefaults.StructuralFeatures; + case DropdownOptionCategory.SpecialCondition: + return _builtInDefaults.SpecialConditions; + default: + return new List(); + } + } + + private static string GetCategoryKey(string title) + { + switch (title) + { + case "交付状态": + return DropdownOptionCategory.DeliveryStatus; + case "工艺方法": + return DropdownOptionCategory.ProcessMethod; + case "结构特征": + return DropdownOptionCategory.StructuralFeature; + case "特殊条件": + return DropdownOptionCategory.SpecialCondition; + default: + return string.Empty; + } + } + private static string ValidateResult(DropdownOptions options) { if (options.DeliveryStatuses == null || options.DeliveryStatuses.Count == 0) diff --git a/UI/TemplateSchemaBindingForm.cs b/UI/TemplateSchemaBindingForm.cs index 26ccb1c..5b51d00 100644 --- a/UI/TemplateSchemaBindingForm.cs +++ b/UI/TemplateSchemaBindingForm.cs @@ -29,6 +29,7 @@ namespace CadParamPluging.UI private readonly List _remarkParamOptions; private readonly ParamCatalog _catalog; + private readonly DropdownOptions _dropdownOptions; private TemplateSchemas _schemas; private sealed class ParamOption @@ -37,11 +38,19 @@ namespace CadParamPluging.UI public string Display { get; set; } } + private sealed class TemplateOptionItem + { + public string Value { get; set; } + public string Display { get; set; } + + public override string ToString() + { + return Display; + } + } + public TemplateSchemaBindingForm( - System.Collections.Generic.IEnumerable projectTypes, - System.Collections.Generic.IEnumerable drawingTypes, - System.Collections.Generic.IEnumerable sheetSizes, - System.Collections.Generic.IEnumerable scales, + DropdownOptions dropdownOptions, ParamCatalog catalog) { Text = "模板参数绑定"; @@ -55,6 +64,8 @@ namespace CadParamPluging.UI _catalog = (catalog ?? ParamCatalog.CreateDefault()).Clone(); _catalog.Normalize(); + _dropdownOptions = (dropdownOptions ?? DropdownOptions.CreateDefault()).Clone(); + _dropdownOptions.Normalize(); _remarkParamOptions = (_catalog.Items ?? Enumerable.Empty()) .Where(p => p != null && string.Equals(p.Group ?? string.Empty, "备注参数", StringComparison.OrdinalIgnoreCase)) @@ -107,10 +118,10 @@ namespace CadParamPluging.UI 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 = CreateCombo(_dropdownOptions.DeliveryStatuses, DropdownOptionCategory.DeliveryStatus); + _cbDrawingType = CreateCombo(_dropdownOptions.ProcessMethods, DropdownOptionCategory.ProcessMethod); + _cbSheetSize = CreateCombo(_dropdownOptions.StructuralFeatures, DropdownOptionCategory.StructuralFeature); + _cbScale = CreateCombo(_dropdownOptions.SpecialConditions, DropdownOptionCategory.SpecialCondition); _cbProjectType.SelectedIndexChanged += (_, __) => UpdateTemplateKeyLabel(); _cbDrawingType.SelectedIndexChanged += (_, __) => UpdateTemplateKeyLabel(); @@ -348,7 +359,7 @@ namespace CadParamPluging.UI ReloadSchemaList(); } - private static ComboBox CreateCombo(System.Collections.Generic.IEnumerable items) + private ComboBox CreateCombo(System.Collections.Generic.IEnumerable items, string category) { var cb = new ComboBox { DropDownStyle = ComboBoxStyle.DropDownList, Width = 220 }; var arr = (items ?? Enumerable.Empty()) @@ -358,7 +369,14 @@ namespace CadParamPluging.UI .ToArray(); if (arr.Length > 0) { - cb.Items.AddRange(arr); + cb.Items.AddRange(arr + .Select(s => new TemplateOptionItem + { + Value = s, + Display = _dropdownOptions.GetDisplayName(category, s) + }) + .Cast() + .ToArray()); cb.SelectedIndex = 0; } return cb; @@ -478,7 +496,7 @@ namespace CadParamPluging.UI } } - private static string FormatSchema(TemplateSchemaDefinition s) + private string FormatSchema(TemplateSchemaDefinition s) { if (s == null) { @@ -486,7 +504,13 @@ namespace CadParamPluging.UI } var name = string.IsNullOrWhiteSpace(s.DisplayName) ? "(未命名)" : s.DisplayName; - return $"{name} | {s.ProjectType}/{s.DrawingType}/{s.SheetSize}/{s.Scale}"; + return string.Format( + "{0} | {1}/{2}/{3}/{4}", + name, + _dropdownOptions.GetDisplayName(DropdownOptionCategory.DeliveryStatus, s.ProjectType), + _dropdownOptions.GetDisplayName(DropdownOptionCategory.ProcessMethod, s.DrawingType), + _dropdownOptions.GetDisplayName(DropdownOptionCategory.StructuralFeature, s.SheetSize), + _dropdownOptions.GetDisplayName(DropdownOptionCategory.SpecialCondition, s.Scale)); } private TemplateSchemaDefinition GetSelectedSchema() @@ -544,7 +568,9 @@ namespace CadParamPluging.UI 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)) + var item = cb.Items[i] as TemplateOptionItem; + var raw = item != null ? item.Value : (cb.Items[i] as string) ?? string.Empty; + if (string.Equals(raw, v, StringComparison.OrdinalIgnoreCase)) { cb.SelectedIndex = i; return; @@ -552,15 +578,35 @@ namespace CadParamPluging.UI } } + private static string GetComboValue(ComboBox cb) + { + if (cb == null) + { + return string.Empty; + } + + var item = cb.SelectedItem as TemplateOptionItem; + if (item != null) + { + return (item.Value ?? string.Empty).Trim(); + } + + return (cb.Text ?? string.Empty).Trim(); + } + private void UpdateTemplateKeyLabel() { - var key = TemplateKeyBuilder.Build(_cbProjectType.Text, _cbDrawingType.Text, _cbSheetSize.Text, _cbScale.Text); + var key = TemplateKeyBuilder.Build( + GetComboValue(_cbProjectType), + GetComboValue(_cbDrawingType), + GetComboValue(_cbSheetSize), + GetComboValue(_cbScale)); _lblTemplateKey.Text = key ?? string.Empty; } private void OnNewSchema() { - if (string.IsNullOrWhiteSpace(_cbProjectType.Text) || string.IsNullOrWhiteSpace(_cbDrawingType.Text)) + if (string.IsNullOrWhiteSpace(GetComboValue(_cbProjectType)) || string.IsNullOrWhiteSpace(GetComboValue(_cbDrawingType))) { MessageBox.Show(this, "请先选择模板四个参数。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; @@ -568,10 +614,10 @@ namespace CadParamPluging.UI var candidate = new TemplateSchemaDefinition { - ProjectType = _cbProjectType.Text, - DrawingType = _cbDrawingType.Text, - SheetSize = _cbSheetSize.Text, - Scale = _cbScale.Text, + ProjectType = GetComboValue(_cbProjectType), + DrawingType = GetComboValue(_cbDrawingType), + SheetSize = GetComboValue(_cbSheetSize), + Scale = GetComboValue(_cbScale), DisplayName = _txtDisplayName.Text }; candidate.Normalize(); @@ -898,10 +944,10 @@ namespace CadParamPluging.UI return; } - schema.ProjectType = _cbProjectType.Text; - schema.DrawingType = _cbDrawingType.Text; - schema.SheetSize = _cbSheetSize.Text; - schema.Scale = _cbScale.Text; + schema.ProjectType = GetComboValue(_cbProjectType); + schema.DrawingType = GetComboValue(_cbDrawingType); + schema.SheetSize = GetComboValue(_cbSheetSize); + schema.Scale = GetComboValue(_cbScale); schema.DisplayName = _txtDisplayName.Text; var selectedParamKeys = _lvParams.Items