feat: port p-rec-annot line-number asset settings

This commit is contained in:
codex
2026-08-07 08:32:15 +03:00
parent ed7218983b
commit a17ad87fc2
3 changed files with 48 additions and 0 deletions
@@ -60,6 +60,11 @@ public sealed record ExistingLineNumberAnnotation(string StableId, string Source
public sealed record LineNumberCommandOperation(string StableId, AnnotationOperationKind Kind, string? Text, AnnotationPoint Position, double Rotation, string Layer, string TextStyle, IReadOnlyList<string> Reasons);
public sealed record LineNumberCommandPlan(IReadOnlyList<LineNumberCommandOperation> Operations);
public sealed record LineNumberApplyPreflight(string StableId, string Text, AnnotationPoint Position, double Rotation, string Layer, string TextStyle);
public sealed record LineNumberTextAsset(string Layer, string TextStyle, double Size, string TextValue, Point2Dto Position);
public sealed record LineNumberLineAsset(string Layer, Point2Dto Start, Point2Dto End);
public sealed record LineNumberMarkerAsset(string Layer, double MaskScaleFactor, IReadOnlyList<LineNumberTextAsset> Texts, IReadOnlyList<LineNumberLineAsset> Lines);
public sealed record LineNumberListAsset(string Layer, double MaskScaleFactor, double LineHeight, double LineSpacingDistance, LineNumberTextAsset MarkerText, LineNumberTextAsset LineNumberText, LineNumberLineAsset Line);
public sealed record AnnotateLineNumbersAssets(LineNumberMarkerAsset Marker, LineNumberListAsset List);
public sealed record GeometrySnapshot
{
@@ -0,0 +1,35 @@
using System.Globalization;
using System.Xml.Linq;
using PRecAnnot.Abstractions;
namespace PRecAnnot.Core;
public sealed class AnnotateLineNumbersSettingsLoader
{
public AnnotateLineNumbersAssets Load(string xml)
{
var lineNumbers = XElement.Parse(xml).Element("LineNumbers") ?? throw Invalid("LineNumbers");
var marker = lineNumbers.Element("Marker") ?? throw Invalid("Marker");
var list = lineNumbers.Element("List") ?? throw Invalid("List");
var texts = marker.Elements("Text").Select(x => Text(x)).ToArray();
var lines = marker.Elements("Line").Select(Line).ToArray();
if (texts.Length == 0 || lines.Length == 0) throw Invalid("MarkerContent");
return new(
new(Required(marker, "layer"), Number(marker, "maskscalefactor"), texts, lines),
new(Required(list, "layer"), Number(list, "maskscalefactor"), Number(list, "lineheight"), Number(list, "linespacingdistance"), Text(RequiredElement(list, "MarkerText"), false), Text(RequiredElement(list, "LineNumberText"), false), Line(RequiredElement(list, "Line"))));
}
private static LineNumberTextAsset Text(XElement value, bool readValue = true) => new(Required(value, "layer"), Required(value, "textstyle"), Number(value, "size"), readValue ? Required(value, "textvalue", true) : string.Empty, new(Number(value, "positionx"), Number(value, "positiony")));
private static LineNumberLineAsset Line(XElement value) => new(Required(value, "layer"), new(Number(value, "startx"), Number(value, "starty")), new(OptionalNumber(value, "endx"), OptionalNumber(value, "endy")));
private static XElement RequiredElement(XElement parent, string name) => parent.Element(name) ?? throw Invalid(name);
private static string Required(XElement value, string name, bool emptyAllowed = false)
{
var attribute = value.Attribute(name) ?? throw Invalid(name);
if (!emptyAllowed && string.IsNullOrWhiteSpace(attribute.Value)) throw Invalid(name);
return attribute.Value;
}
private static double Number(XElement value, string name) => Parse(Required(value, name));
private static double OptionalNumber(XElement value, string name) => value.Attribute(name) is { } attribute ? Parse(attribute.Value) : 0;
private static double Parse(string value) => double.TryParse(value.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) ? result : throw Invalid("number");
private static InvalidDataException Invalid(string field) => new("LINE_NUMBER_SETTINGS_INVALID:" + field);
}