diff --git a/Cad/TemplateDrawingService.cs b/Cad/TemplateDrawingService.cs index f966326..52ebe8a 100644 --- a/Cad/TemplateDrawingService.cs +++ b/Cad/TemplateDrawingService.cs @@ -982,7 +982,7 @@ namespace CadParamPluging.Cad var searchRegionMinX = f.MaxPoint.X - 200.0; // Assume title block width < 200 var searchRegionMinY = f.MinPoint.Y; - var searchRegionMaxY = f.MinPoint.Y + 150.0; // Assume title block height < 150 + var searchRegionMaxY = f.MinPoint.Y + 80.0; // Reduce to avoid picking up drawing lines (Title block usually < 80mm) double tableTopY = f.MinPoint.Y + 60.0; // Default fallback (e.g. 60mm from bottom) @@ -1032,22 +1032,58 @@ namespace CadParamPluging.Cad var insertY = tableTopY + 2.0; var insertPoint = new Point3d(insertX, insertY, 0); + var textHeight = 3.2; // 9号字 (interpreted as 9pt approx 3.2mm) var mt = new MText(); - mt.Contents = ToMTextContents(textToShow); + // Set font to SimSun (宋体) + mt.Contents = @"{\fSimSun|b0|i0|c134|p2;" + ToMTextContents(textToShow) + "}"; mt.Location = insertPoint; - mt.TextHeight = 5.0; - mt.Attachment = AttachmentPoint.BottomRight; // Anchor at bottom-right, grows up and left + mt.TextHeight = textHeight; + mt.Attachment = AttachmentPoint.BottomRight; // Anchor at bottom-right mt.Width = 0; // No wrap width, auto - mt.ColorIndex = 7; + mt.ColorIndex = 7; // White + + // Create White Border + // Estimate dimensions: Chinese char width approx equals height + // Adding padding to visually center the text in the box + double charWidthFactor = 1.0; + double estimatedTextWidth = textToShow.Length * textHeight * charWidthFactor; + double paddingH = 1.5; // Horizontal padding + double paddingV = 1.5; // Vertical padding + + // Since Attachment is BottomRight: + // Text occupies roughly: [X - Width, X] x [Y, Y + Height] + // We draw box around this area with padding + + var boxMinX = insertX - estimatedTextWidth - paddingH; + var boxMaxX = insertX + paddingH; + var boxMinY = insertY - paddingV; + var boxMaxY = insertY + textHeight + paddingV; + + var poly = new Polyline(); + poly.AddVertexAt(0, new Point2d(boxMinX, boxMinY), 0, 0, 0); + poly.AddVertexAt(1, new Point2d(boxMaxX, boxMinY), 0, 0, 0); + poly.AddVertexAt(2, new Point2d(boxMaxX, boxMaxY), 0, 0, 0); + poly.AddVertexAt(3, new Point2d(boxMinX, boxMaxY), 0, 0, 0); + poly.Closed = true; + poly.ColorIndex = 7; // White (Index 7 is White/Black depending on bg, usually White for plot) try { var layerTbl = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); - if (layerTbl.Has("TEXT")) mt.Layer = "TEXT"; - else if (layerTbl.Has("文字")) mt.Layer = "文字"; - else mt.Layer = "0"; + string targetLayer = "0"; + if (layerTbl.Has("TEXT")) targetLayer = "TEXT"; + else if (layerTbl.Has("文字")) targetLayer = "文字"; + + // Assign layer to both MText and Box + mt.Layer = targetLayer; + poly.Layer = targetLayer; } - catch { mt.Layer = "0"; } + catch { } + + space.AppendEntity(poly); + tr.AddNewlyCreatedDBObject(poly, true); + + space.AppendEntity(mt); tr.AddNewlyCreatedDBObject(mt, true); diff --git a/Common/NoteTemplateEngine.cs b/Common/NoteTemplateEngine.cs index b3c58fc..a8aa49a 100644 --- a/Common/NoteTemplateEngine.cs +++ b/Common/NoteTemplateEngine.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace CadParamPluging.Common { @@ -181,79 +182,191 @@ namespace CadParamPluging.Common public static string Render(string templateText, IEnumerable bindings, Func getValue) { templateText = templateText ?? string.Empty; - + + // Normalize newlines to \n var s = NormalizeNewLines(templateText); + + // Split into lines to process removal logic + var lines = s.Split(new[] { '\n' }, StringSplitOptions.None); + // Build map var map = new Dictionary(); foreach (var b in bindings ?? Enumerable.Empty()) { - if (b == null) + if (b != null && b.Index > 0 && !string.IsNullOrWhiteSpace(b.ParamKey)) { - continue; - } - - if (b.Index <= 0) - { - continue; - } - - var key = (b.ParamKey ?? string.Empty).Trim(); - if (key.Length == 0) - { - continue; - } - - if (!map.ContainsKey(b.Index)) - { - map[b.Index] = key; + var key = b.ParamKey.Trim(); + if (!map.ContainsKey(b.Index)) + { + map[b.Index] = key; + } } } - var sb = new StringBuilder(s.Length + 64); + var resultLines = new List(); var placeholderIndex = 0; - for (var i = 0; i < s.Length;) + foreach (var line in lines) { - if (s[i] != '*') + // 1. Scan line to determine if it should be skipped (if any param value is "空") + bool shouldSkip = false; + int localPlaceholderCount = 0; + + // We must traverse the line to find placeholders correctly to sync index + for (int i = 0; i < line.Length; ) { - sb.Append(s[i]); - i++; - continue; - } + if (line[i] != '*') + { + i++; + continue; + } - var j = i; - while (j < s.Length && s[j] == '*') - { - j++; - } + // Check for escape **** + int j = i; + while (j < line.Length && line[j] == '*') j++; + + if (j - i == 4) + { + // **** counts as text, not placeholder + i = j; + continue; + } - var runLen = j - i; - if (runLen == 4) - { - sb.Append("****"); - i = j; - continue; - } - - for (var k = 0; k < runLen; k++) - { - placeholderIndex++; - if (map.TryGetValue(placeholderIndex, out var key) && getValue != null) + // Run of * (length != 4) + int runLen = j - i; + for (int k = 0; k < runLen; k++) { - var v = getValue(key); - if (!string.IsNullOrWhiteSpace(v)) + localPlaceholderCount++; + int currentIdx = placeholderIndex + localPlaceholderCount; + + if (map.TryGetValue(currentIdx, out var key) && getValue != null) { - sb.Append(v); - continue; + var val = getValue(key); + // Check for strict "空" + if (string.Equals(val, "空", StringComparison.OrdinalIgnoreCase)) + { + // Exception: MarkingContent (标刻内容) should NOT cause line skip + if (!string.Equals(key, "MarkingContent", StringComparison.OrdinalIgnoreCase)) + { + shouldSkip = true; + } + } } } - sb.Append('*'); + i = j; } - i = j; + // 2. If line is skipped, just update global index and continue + if (shouldSkip) + { + placeholderIndex += localPlaceholderCount; + continue; + } + + // 3. If line matches, render it + // We re-scan to apply values. + // Using a temp index starting from where we were + var sb = new StringBuilder(line.Length + 64); + int tempIdx = placeholderIndex; + + for (int i = 0; i < line.Length; ) + { + if (line[i] != '*') + { + sb.Append(line[i]); + i++; + continue; + } + + int j = i; + while (j < line.Length && line[j] == '*') j++; + + if (j - i == 4) + { + sb.Append("****"); + i = j; + continue; + } + + int runLen = j - i; + for (int k = 0; k < runLen; k++) + { + tempIdx++; + if (map.TryGetValue(tempIdx, out var key) && getValue != null) + { + var v = getValue(key); + if (!string.IsNullOrWhiteSpace(v)) + { + // Handle "空" value + if (string.Equals(v, "空", StringComparison.OrdinalIgnoreCase)) + { + if (string.Equals(key, "MarkingContent", StringComparison.OrdinalIgnoreCase)) + { + // MarkingContent -> render empty string + // (Separators will be cleaned up later) + } + else + { + // Other keys -> render empty (should imply hidden line, + // but if we are here, it means some OTHER key prevented hiding? + // Or this case shouldn't happen if mixed? + // Assuming if line is not skipped, we treat "空" as empty string.) + } + } + else + { + sb.Append(v); + } + } + else + { + // Keep * if value is missing/empty (but not "空" which was handled) + sb.Append('*'); + } + } + else + { + sb.Append('*'); + } + } + i = j; + } + + var renderedLine = sb.ToString(); + + // 3.1 Clean up redundant separators for MarkingContent removal + // Replace "、、" with "、" + renderedLine = Regex.Replace(renderedLine, @"、\s*、", "、"); + // Replace ":、" with ":" (start of list) + renderedLine = Regex.Replace(renderedLine, @"([::])\s*、", "$1"); + // Replace "、。" with "。" (end of list) + renderedLine = Regex.Replace(renderedLine, @"、\s*([。.;;])", "$1"); + // Trim trailing "、" if it exists (no period) + renderedLine = Regex.Replace(renderedLine, @"、\s*$", ""); + + resultLines.Add(renderedLine); + placeholderIndex += localPlaceholderCount; } - return sb.ToString(); + // 4. Renumbering Logic + var renumberRegex = new Regex(@"^(\s*)(\d+)([、\.])"); + int counter = 1; + + for (int i = 0; i < resultLines.Count; i++) + { + var match = renumberRegex.Match(resultLines[i]); + if (match.Success) + { + var prefix = match.Groups[1].Value; + var suffix = match.Groups[3].Value; + + var newLine = prefix + counter + suffix + resultLines[i].Substring(match.Length); + resultLines[i] = newLine; + counter++; + } + } + + return string.Join("\n", resultLines); } ///