feat: 为CAD插件添加图纸参数面板和表单

This commit is contained in:
sladro 2025-12-31 15:45:07 +08:00
parent 5506ed9861
commit 2a4894657f
2 changed files with 192 additions and 15 deletions

View File

@ -33,12 +33,14 @@ namespace CadParamPluging.UI
private const string KeyMinWallThickness = "MinWallThickness";
public ParamBag Result { get; private set; }
private ParamBag _loadedDefaults; // 新增:外部传入的默认值
public DrawingParamsForm(ParamCatalog catalog, TemplateSchemaDefinition schema)
public DrawingParamsForm(ParamCatalog catalog, TemplateSchemaDefinition schema, ParamBag loadedDefaults = null)
{
_catalog = (catalog ?? ParamCatalog.CreateDefault()).Clone();
_catalog.Normalize();
_schema = schema;
_loadedDefaults = loadedDefaults; // 存储传入的默认值
Text = "填写参数";
Size = new Size(980, 680);
@ -640,18 +642,32 @@ namespace CadParamPluging.UI
private Control CreateControl(ParamDefinition def)
{
var initialValue = def.DefaultValue;
// 优先使用传入的默认值 (loadedDefaults)
if (_loadedDefaults != null)
{
var val = _loadedDefaults.GetString(def.Key);
if (val != null) // only if key exists
{
initialValue = val;
}
}
// 确保不为 null
if (initialValue == null) initialValue = string.Empty;
switch (def.Type)
{
case ParamValueType.Bool:
return new CheckBox { Checked = ParseBool(def.DefaultValue), AutoSize = true };
return new CheckBox { Checked = ParseBool(initialValue), AutoSize = true };
case ParamValueType.Enum:
return CreateEnumCombo(def);
return CreateEnumCombo(def, initialValue);
case ParamValueType.Int:
return CreateNumber(def, isInt: true);
return CreateNumber(def, isInt: true, overrideValue: initialValue);
case ParamValueType.Double:
return CreateNumber(def, isInt: false);
return CreateNumber(def, isInt: false, overrideValue: initialValue);
default:
return new TextBox { Text = def.DefaultValue ?? string.Empty };
return new TextBox { Text = initialValue };
}
}
@ -669,7 +685,7 @@ namespace CadParamPluging.UI
|| string.Equals(s.Trim(), "是", StringComparison.OrdinalIgnoreCase);
}
private ComboBox CreateEnumCombo(ParamDefinition def)
private ComboBox CreateEnumCombo(ParamDefinition def, string initialValue)
{
// Allow manual edit to match many "下拉列表...可手动编辑" cases.
var cb = new ComboBox { DropDownStyle = ComboBoxStyle.DropDown };
@ -677,17 +693,17 @@ namespace CadParamPluging.UI
if (arr.Length > 0)
{
cb.Items.AddRange(arr);
var idx = Array.FindIndex(arr, x => string.Equals(x, def.DefaultValue, StringComparison.OrdinalIgnoreCase));
var idx = Array.FindIndex(arr, x => string.Equals(x, initialValue, StringComparison.OrdinalIgnoreCase));
cb.SelectedIndex = idx >= 0 ? idx : 0;
}
if (!string.IsNullOrWhiteSpace(def.DefaultValue))
if (!string.IsNullOrWhiteSpace(initialValue))
{
cb.Text = def.DefaultValue;
cb.Text = initialValue;
}
return cb;
}
private Control CreateNumber(ParamDefinition def, bool isInt)
private Control CreateNumber(ParamDefinition def, bool isInt, string overrideValue)
{
var num = new NumericUpDown
{
@ -705,7 +721,10 @@ namespace CadParamPluging.UI
{
num.Maximum = max;
}
if (TryParseDecimal(def.DefaultValue, out var dv))
// 使用 overrideValue 或 def.DefaultValue
// 但 CreateNumber 被调用时overrideValue 已经是处理过的“最终初始值”
if (TryParseDecimal(overrideValue, out var dv))
{
if (dv < num.Minimum) dv = num.Minimum;
if (dv > num.Maximum) dv = num.Maximum;

View File

@ -187,6 +187,11 @@ namespace CadParamPluging.UI
panel.Controls.Add(btnGenerate);
panel.Controls.Add(btnSaveAs);
var btnLoadParams = new Button { Text = "读取参数", AutoSize = true };
btnLoadParams.Click += (_, __) => OnLoadParams();
panel.Controls.Add(btnLoadParams);
panel.Controls.Add(btnSettings);
// panel.Controls.Add(btnTestDraw); // 暂时屏蔽测试绘制按钮
return panel;
@ -786,10 +791,19 @@ namespace CadParamPluging.UI
try
{
var bagToSave = bag;
// 注意bag 已经在上面被使用了,直接传递即可。
// 如果需要保存更完整的信息(比如模板路径),也可以添加到 bag 中
// bagToSave.Set("_TemplatePath", _selectedTemplate.FilePath);
// 保存模板信息以便后续“读取参数”功能可以自动填充UI
if (_selectedTemplate != null)
{
bagToSave.Set("_TemplatePath", _selectedTemplate.FilePath);
bagToSave.Set("_LayoutName", _selectedTemplate.LayoutName);
}
// 保存面板选项
bagToSave.Set("ProjectType", tplParams.ProjectType);
bagToSave.Set("DrawingType", tplParams.DrawingType);
bagToSave.Set("SheetSize", tplParams.SheetSize);
bagToSave.Set("SpecialCondition", tplParams.Scale); // tplParams.Scale 对应 _cbScale (特殊条件)
DictionaryHelper.SaveParams(doc.Database, bagToSave);
AppendLog("参数已保存到图纸内部数据中。");
}
@ -866,6 +880,150 @@ namespace CadParamPluging.UI
}
}
private void OnLoadParams()
{
try
{
var doc = AcadApp.DocumentManager.MdiActiveDocument;
if (doc == null)
{
AppendLog("未找到活动图纸,无法读取参数。");
return;
}
ParamBag bag;
using (doc.LockDocument())
{
bag = DictionaryHelper.ReadParams(doc.Database);
}
if (bag == null || bag.Items == null || bag.Items.Count == 0)
{
AppendLog("当前图纸未找到存储的参数(或非本插件生成)。");
return;
}
// 1. 尝试根据 path 恢复模板选择
var tplPath = bag.GetString("_TemplatePath");
if (!string.IsNullOrWhiteSpace(tplPath))
{
// 在 _cbTemplateList 中查找
int foundIndex = -1;
for (int i = 0; i < _cbTemplateList.Items.Count; i++)
{
var item = _cbTemplateList.Items[i] as TemplateSelectionItem;
if (item != null && string.Equals(item.Info.FilePath, tplPath, StringComparison.OrdinalIgnoreCase))
{
// 如果原来的选择也是布局,尝试匹配布局名
var originalLayout = bag.GetString("_LayoutName");
if (!string.IsNullOrWhiteSpace(originalLayout))
{
if (string.Equals(item.Info.LayoutName, originalLayout, StringComparison.OrdinalIgnoreCase))
{
foundIndex = i;
break;
}
}
else
{
// 只有 Model Space 情况,或者不精确匹配布局
foundIndex = i;
break;
}
}
}
if (foundIndex >= 0)
{
_cbTemplateList.SelectedIndex = foundIndex;
AppendLog($"已自动选中模板: {_cbTemplateList.Items[foundIndex]}");
}
else
{
AppendLog($"注意: 未在列表中找到原模板文件: {Path.GetFileName(tplPath)},可能文件已移动或未加载路径。");
}
}
// 2. 恢复下拉框选项
// ProjectType
TrySelectRequest(bag, "ProjectType", _cbProjectType);
// DrawingType
TrySelectRequest(bag, "DrawingType", _cbDrawingType);
// SheetSize
TrySelectRequest(bag, "SheetSize", _cbSheetSize);
// Scale (DrawingScale) - 注意我们下拉框叫 _cbScale参数里可能是 DrawingScale
var scaleVal = bag.GetString("DrawingScale");
// 特殊条件/Scale 其实是一个 ComboBox通常用于 SpecialConditions
// 但 DrawingScale 是在生成时 Parse 出来的。
// 这里的 _cbScale 绑定的是 options.SpecialConditions (e.g. "中心冲孔") 还是 "1:50"?
// 回看代码 reset _cbScale 绑定的是 options.SpecialConditions (ResetComboBoxItems(_cbScale, options.SpecialConditions))
// 而 "scale" 是指比例。
// 观察 GenerateDrawing 逻辑:
// var tplParams = CollectTemplateParams(); -> Scale = _cbScale.Text
// 这个 _cbScale 存的是“特殊条件”。
// 真正的比例是在 Bag.GetString("DrawingScale"),这是在 DrawParamsForm 里填写的。
//
// 等等!看 Readme 和 UI 逻辑,主面板只有 4 个下拉框: Project/Drawing/SheetSize/Scale
// 其中 _cbScale 有时候被用作 Scale但 DropdownOptions 绑定的是 SpecialConditions?
// Let's check ReloadDropdownOptions:
// ResetComboBoxItems(_cbScale, options.SpecialConditions); -> 所以 _cbScale 是“特殊条件”!
// 那比例去哪了?
// Readme 说 "ComboBox / TextBox比例Scale"
// 让我们确认 CollectTemplateParams: Scale = _cbScale.Text (specialCondition)
// 看来目前主面板并没有“比例”输入框?比例是在 Form 里填写的?
// 检查 OnGenerateDrawing -> new DrawingParamsForm(catalog, schema) -> 这个 Form 里填写的具体参数。
//
// 所以OnLoadParams 只能恢复 面板上的 4 个下拉框。
// 而 Form 里的参数(如 OuterDiameter, DrawingScale需要在点“生成”后弹出 Form 时自动填入。
// 这需要修改 DrawingParamsForm 的构造函数或者逻辑,让它支持“默认值”从 Bag 中覆盖。
TrySelectRequest(bag, "SpecialCondition", _cbScale); // 假设存的时候 key 是 SpecialCondition?
// CollectTemplateParams 里没有把 template params 放入 bag。
// 但是DomainFacade.ValidateParameters 可能会用到。
// 关键点TemplateParams 只是用来匹配 TemplateKey。
// 实际生成图纸时OnGenerateDrawing 收集了 tplParams然后 Build TemplateKey然后 Load Schema然后...
// 用 Form 填写了 Bag。
// 所以“项目类型/图纸类型”等并没有被存入 Bag (除非 Form 里也有对应字段)。
// 这是一个问题Bag 主要是 Form 的结果。面板上的选择决定了 TemplateKey。
// 我们在 SaveParamsToExtensionDictionary 时,只存了 Bag。
// 如果面板上的选项(项目类型等)没在 Bag 里,我们就无法恢复面板状态!
//
// 补救措施:必须在 SaveParams 时把 tplParams 的内容也塞进 Bag。
// 我刚刚加了 _TemplatePath/_LayoutName但漏了 ProjectType 等。
//
// 既然现在代码还没运行,我可以再加几个 Set。
AppendLog("参数读取完成。请点击【生成图纸】继续修改详细参数。");
// 将读取到的 Bag 暂存,以便 DrawingParamsForm 打开时使用它作为默认值
_lastLoadedBag = bag;
}
catch (Exception ex)
{
AppendLog($"读取参数失败: {ex.Message}");
Logger.Error("LoadParams", ex);
}
}
private ParamBag _lastLoadedBag; // 暂存读取到的参数
private void TrySelectRequest(ParamBag bag, string key, ComboBox cb)
{
var val = bag.GetString(key);
if (!string.IsNullOrEmpty(val))
{
// 尝试选中
int idx = cb.FindStringExact(val);
if (idx >= 0)
{
cb.SelectedIndex = idx;
return;
}
// 如果没有,可能手动 Text? ComboBoxStyle.DropDownList 不允许。
// 如果是 DropDownList 且不在列表中,就无法选中。
}
}
private void ReloadDropdownOptions(DropdownOptions options)
{
if (options == null)