diff --git a/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Annotation.cs b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Annotation.cs new file mode 100644 index 00000000..e99deb58 --- /dev/null +++ b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Annotation.cs @@ -0,0 +1,92 @@ +using System.Text.Json.Serialization; + +namespace EnvelopeGenerator.GeneratorAPI.Models.PsPdfKitAnnotation; + +public record Annotation : IAnnotation +{ + public required string Name { get; init; } + + #region Bound Annotation + [JsonIgnore] + public string? HorBoundAnnotName { get; init; } + + [JsonIgnore] + public string? VerBoundAnnotName { get; init; } + #endregion + + #region Layout + [JsonIgnore] + public double? MarginLeft { get; set; } + + [JsonIgnore] + public double MarginLeftRatio { get; init; } = 1; + + [JsonIgnore] + public double? MarginTop { get; set; } + + [JsonIgnore] + public double MarginTopRatio { get; init; } = 1; + + public double? Width { get; set; } + + [JsonIgnore] + public double WidthRatio { get; init; } = 1; + + public double? Height { get; set; } + + [JsonIgnore] + public double HeightRatio { get; init; } = 1; + #endregion + + #region Position + public double Left => (MarginLeft ?? 0) + (HorBoundAnnot?.HorBoundary ?? 0); + + public double Top => (MarginTop ?? 0) + (VerBoundAnnot?.VerBoundary ?? 0); + #endregion + + #region Boundary + [JsonIgnore] + public double HorBoundary => Left + (Width ?? 0); + + [JsonIgnore] + public double VerBoundary => Top + (Height ?? 0); + #endregion + + #region BoundAnnot + [JsonIgnore] + public Annotation? HorBoundAnnot { get; set; } + + [JsonIgnore] + public Annotation? VerBoundAnnot { get; set; } + #endregion + + public Color? BackgroundColor { get; init; } + + #region Border + public Color? BorderColor { get; init; } + + public string? BorderStyle { get; init; } + + public int? BorderWidth { get; set; } + #endregion + + [JsonIgnore] + internal Annotation Default + { + set + { + // To set null value, annotation must have null (0) value but null must has non-null value + if (MarginLeft == null && value.MarginLeft != null) + MarginLeft = value.MarginLeft * MarginLeftRatio; + + if (MarginTop == null && value.MarginTop != null) + MarginTop = value.MarginTop * MarginTopRatio; + + if (Width == null && value.Width != null) + Width = value.Width * WidthRatio; + + if (Height == null && value.Height != null) + Height = value.Height * HeightRatio; + } + } +}; \ No newline at end of file diff --git a/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/AnnotationParams.cs b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/AnnotationParams.cs new file mode 100644 index 00000000..6413a20d --- /dev/null +++ b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/AnnotationParams.cs @@ -0,0 +1,79 @@ +using System.Text.Json.Serialization; + +namespace EnvelopeGenerator.GeneratorAPI.Models.PsPdfKitAnnotation; + +public class AnnotationParams +{ + public AnnotationParams() + { + _AnnotationJSObjectInitor = new(CreateAnnotationJSObject); + } + + public Background? Background { get; init; } + + #region Annotation + [JsonIgnore] + public Annotation? DefaultAnnotation { get; init; } + + private readonly List _annots = new List(); + + public bool TryGet(string name, out Annotation annotation) + { +#pragma warning disable CS8601 // Possible null reference assignment. + annotation = _annots.FirstOrDefault(a => a.Name == name); +#pragma warning restore CS8601 // Possible null reference assignment. + return annotation is not null; + } + + public required IEnumerable Annotations + { + get => _annots; + init + { + _annots = value.ToList(); + + if (DefaultAnnotation is not null) + foreach (var annot in _annots) + annot.Default = DefaultAnnotation; + + for (int i = 0; i < _annots.Count; i++) + { + #region set bound annotations + // horizontal + if (_annots[i].HorBoundAnnotName is string horBoundAnnotName) + if (TryGet(horBoundAnnotName, out var horBoundAnnot)) + _annots[i].HorBoundAnnot = horBoundAnnot; + else + throw new InvalidOperationException($"{horBoundAnnotName} added as bound anotation. However, it is not defined."); + + // vertical + if (_annots[i].VerBoundAnnotName is string verBoundAnnotName) + if (TryGet(verBoundAnnotName, out var verBoundAnnot)) + _annots[i].VerBoundAnnot = verBoundAnnot; + else + throw new InvalidOperationException($"{verBoundAnnotName} added as bound anotation. However, it is not defined."); + #endregion + } + } + } + #endregion + + #region AnnotationJSObject + private Dictionary CreateAnnotationJSObject() + { + var dict = _annots.ToDictionary(a => a.Name.ToLower(), a => a as IAnnotation); + + if (Background is not null) + { + Background.Locate(_annots); + dict.Add(Background.Name.ToLower(), Background); + } + + return dict; + } + + private readonly Lazy> _AnnotationJSObjectInitor; + + public Dictionary AnnotationJSObject => _AnnotationJSObjectInitor.Value; + #endregion +} diff --git a/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Background.cs b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Background.cs new file mode 100644 index 00000000..16d139e9 --- /dev/null +++ b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Background.cs @@ -0,0 +1,58 @@ +using System.Text.Json.Serialization; + +namespace EnvelopeGenerator.GeneratorAPI.Models.PsPdfKitAnnotation; + +/// +/// The Background is an annotation for the PSPDF Kit. However, it has no function. +/// It is only the first annotation as a background for other annotations. +/// +public record Background : IAnnotation +{ + [JsonIgnore] + public double Margin { get; init; } + + public string Name { get; } = "Background"; + + public double? Width { get; set; } + + public double? Height { get; set; } + + public double Left { get; set; } + + public double Top { get; set; } + + public Color? BackgroundColor { get; init; } + + #region Border + public Color? BorderColor { get; init; } + + public string? BorderStyle { get; init; } + + public int? BorderWidth { get; set; } + #endregion + + public void Locate(IEnumerable annotations) + { + // set Top + if (annotations.MinBy(a => a.Top)?.Top is double minTop) + Top = minTop; + + // set Left + if (annotations.MinBy(a => a.Left)?.Left is double minLeft) + Left = minLeft; + + // set Width + if(annotations.MaxBy(a => a.GetRight())?.GetRight() is double maxRight) + Width = maxRight - Left; + + // set Height + if (annotations.MaxBy(a => a.GetBottom())?.GetBottom() is double maxBottom) + Height = maxBottom - Top; + + // add margins + Top -= Margin; + Left -= Margin; + Width += Margin * 2; + Height += Margin * 2; + } +} diff --git a/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Color.cs b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Color.cs new file mode 100644 index 00000000..6672edd1 --- /dev/null +++ b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Color.cs @@ -0,0 +1,10 @@ +namespace EnvelopeGenerator.GeneratorAPI.Models.PsPdfKitAnnotation; + +public record Color +{ + public int R { get; init; } = 0; + + public int G { get; init; } = 0; + + public int B { get; init; } = 0; +} diff --git a/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Extensions.cs b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Extensions.cs new file mode 100644 index 00000000..35f0be06 --- /dev/null +++ b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/Extensions.cs @@ -0,0 +1,8 @@ +namespace EnvelopeGenerator.GeneratorAPI.Models.PsPdfKitAnnotation; + +public static class Extensions +{ + public static double GetRight(this IAnnotation annotation) => annotation.Left + annotation?.Width ?? 0; + + public static double GetBottom(this IAnnotation annotation) => annotation.Top + annotation?.Height ?? 0; +} diff --git a/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/IAnnotation.cs b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/IAnnotation.cs new file mode 100644 index 00000000..d6ab1019 --- /dev/null +++ b/EnvelopeGenerator.GeneratorAPI/Models/PsPdfKitAnnotation/IAnnotation.cs @@ -0,0 +1,22 @@ +namespace EnvelopeGenerator.GeneratorAPI.Models.PsPdfKitAnnotation; + +public interface IAnnotation +{ + string Name { get; } + + double? Width { get; } + + double? Height { get; } + + double Left { get; } + + double Top { get; } + + Color? BackgroundColor { get; } + + Color? BorderColor { get; } + + string? BorderStyle { get; } + + int? BorderWidth { get; } +}