Add dynamic color support for receivers
Introduced a `Color` property to `ReceiverDraft` and `SignatureFieldDraft` models, enabling dynamic color assignment from a predefined palette (`ReceiverPalette`). Updated the UI to reflect receiver-specific colors in the sender-receiver chips, placement mode hint bar, and signature placement button. Refactored PDF rendering logic to dynamically derive visual styles (fill, border, and text colors) from receiver colors. Added a `HexToXColor` utility for converting hex color strings to `PdfSharp.Drawing.XColor`. Removed hardcoded visual styles and replaced them with dynamic, receiver-specific styling. Simplified receiver addition logic to automatically assign colors from the palette. These changes improve clarity and maintainability while enhancing the user experience.
This commit is contained in:
@@ -74,7 +74,8 @@
|
||||
<div class="sender-receivers-list">
|
||||
@foreach (var receiver in _receivers)
|
||||
{
|
||||
<div class="sender-receiver-chip">
|
||||
<div class="sender-receiver-chip"
|
||||
style="border-left: 3px solid @receiver.Color;">
|
||||
<div class="sender-receiver-chip__body">
|
||||
<div class="sender-receiver-chip__name">@receiver.FullName</div>
|
||||
<div class="sender-receiver-chip__email">@receiver.Email</div>
|
||||
@@ -87,6 +88,7 @@
|
||||
<button class="pdf-toolbar__btn pdf-toolbar__btn--signature-change sender-toolbar-action-btn sender-toolbar-action-btn--compact
|
||||
@(_pendingReceiverForPlacement?.Id == receiver.Id ? "pdf-toolbar__btn--signature-change-active" : "")"
|
||||
@onclick="() => ActivatePlacementForReceiver(receiver)"
|
||||
style="@(_pendingReceiverForPlacement?.Id == receiver.Id ? $"background:{receiver.Color};color:#fff;border-color:{receiver.Color};" : $"color:{receiver.Color};border-color:{receiver.Color};")"
|
||||
title="Signaturfeld platzieren">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10z" />
|
||||
@@ -155,7 +157,7 @@
|
||||
@* Placement mode hint bar *@
|
||||
@if (_pendingReceiverForPlacement is not null)
|
||||
{
|
||||
<div style="background: #4F46E5; color: white; font-size: 0.75rem; font-weight: 500;
|
||||
<div style="background: @_pendingReceiverForPlacement.Color; color: white; font-size: 0.75rem; font-weight: 500;
|
||||
padding: 0.3rem 1.5rem; text-align: center; letter-spacing: 0.01em;">
|
||||
📌 Klicken Sie auf die Stelle im Dokument für <strong>@_pendingReceiverForPlacement.FullName</strong>.
|
||||
<button @onclick="CancelPlacement"
|
||||
@@ -483,7 +485,8 @@
|
||||
XPt: xPt,
|
||||
YPt: yPt,
|
||||
Page: page1Based,
|
||||
ReceiverName: _pendingReceiverForPlacement.FullName);
|
||||
ReceiverName: _pendingReceiverForPlacement.FullName,
|
||||
Color: _pendingReceiverForPlacement.Color);
|
||||
|
||||
_signatureFields.Add(field);
|
||||
_pendingReceiverForPlacement = null;
|
||||
@@ -565,25 +568,6 @@
|
||||
var document = PdfSharp.Pdf.IO.PdfReader.Open(
|
||||
inputMs, PdfSharp.Pdf.IO.PdfDocumentOpenMode.Modify);
|
||||
|
||||
// Visual style — same palette as the receiver-side placeholder
|
||||
var fillBrush = new PdfSharp.Drawing.XSolidBrush(PdfSharp.Drawing.XColor.FromArgb( 40, 60, 80, 160));
|
||||
var borderPen = new PdfSharp.Drawing.XPen(PdfSharp.Drawing.XColor.FromArgb(200, 60, 80, 200), 1.5);
|
||||
var textBrush = new PdfSharp.Drawing.XSolidBrush(PdfSharp.Drawing.XColor.FromArgb(200, 40, 60, 140));
|
||||
var nameBrush = new PdfSharp.Drawing.XSolidBrush(PdfSharp.Drawing.XColor.FromArgb(255, 30, 30, 100));
|
||||
var fontLabel = new PdfSharp.Drawing.XFont("Arial", 9, PdfSharp.Drawing.XFontStyleEx.Bold);
|
||||
var fontName = new PdfSharp.Drawing.XFont("Arial", 7, PdfSharp.Drawing.XFontStyleEx.Regular);
|
||||
|
||||
var fmtCenter = new PdfSharp.Drawing.XStringFormat
|
||||
{
|
||||
Alignment = PdfSharp.Drawing.XStringAlignment.Center,
|
||||
LineAlignment = PdfSharp.Drawing.XLineAlignment.Center,
|
||||
};
|
||||
var fmtBottomCenter = new PdfSharp.Drawing.XStringFormat
|
||||
{
|
||||
Alignment = PdfSharp.Drawing.XStringAlignment.Center,
|
||||
LineAlignment = PdfSharp.Drawing.XLineAlignment.Far,
|
||||
};
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
int pageIndex = field.Page - 1;
|
||||
@@ -592,6 +576,21 @@
|
||||
var page = document.Pages[pageIndex];
|
||||
using var gfx = PdfSharp.Drawing.XGraphics.FromPdfPage(page);
|
||||
|
||||
// Derive colours from the receiver's hex colour
|
||||
var fillBrush = new PdfSharp.Drawing.XSolidBrush(HexToXColor(field.Color, alpha: 35));
|
||||
var borderPen = new PdfSharp.Drawing.XPen(HexToXColor(field.Color, alpha: 210), 1.5);
|
||||
var textBrush = new PdfSharp.Drawing.XSolidBrush(HexToXColor(field.Color, alpha: 200));
|
||||
var nameBrush = new PdfSharp.Drawing.XSolidBrush(HexToXColor(field.Color, alpha: 230));
|
||||
|
||||
var fontLabel = new PdfSharp.Drawing.XFont("Arial", 9, PdfSharp.Drawing.XFontStyleEx.Bold);
|
||||
var fontName = new PdfSharp.Drawing.XFont("Arial", 7, PdfSharp.Drawing.XFontStyleEx.Regular);
|
||||
|
||||
var fmtCenter = new PdfSharp.Drawing.XStringFormat
|
||||
{
|
||||
Alignment = PdfSharp.Drawing.XStringAlignment.Center,
|
||||
LineAlignment = PdfSharp.Drawing.XLineAlignment.Center,
|
||||
};
|
||||
|
||||
var rect = new PdfSharp.Drawing.XRect(field.XPt, field.YPt, SigWidthPt, SigHeightPt);
|
||||
|
||||
gfx.DrawRectangle(fillBrush, rect);
|
||||
@@ -616,6 +615,13 @@
|
||||
return outputMs.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>Converts a CSS hex colour string (e.g. "#4F46E5") to a PdfSharp XColor.</summary>
|
||||
static PdfSharp.Drawing.XColor HexToXColor(string hex, int alpha)
|
||||
{
|
||||
var c = System.Drawing.ColorTranslator.FromHtml(hex);
|
||||
return PdfSharp.Drawing.XColor.FromArgb(alpha, c.R, c.G, c.B);
|
||||
}
|
||||
|
||||
// ── Receiver popup ──
|
||||
void OpenAddReceiverPopup()
|
||||
{
|
||||
@@ -777,22 +783,36 @@
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
_receivers.Add(new ReceiverDraft(Guid.NewGuid(), fullName, email, phoneNumber));
|
||||
_receivers.Add(new ReceiverDraft(Guid.NewGuid(), fullName, email, phoneNumber,
|
||||
ReceiverPalette[_receivers.Count % ReceiverPalette.Length]));
|
||||
PersistSession();
|
||||
CloseAddReceiverPopup();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// ── Models ──
|
||||
record SignatureFieldDraft(double XPt, double YPt, int Page, string ReceiverName);
|
||||
record SignatureFieldDraft(double XPt, double YPt, int Page, string ReceiverName, string Color);
|
||||
|
||||
record NormalisedCoords(double NormX, double NormY, int PageIndex);
|
||||
|
||||
record ReceiverDraft(Guid Id, string FullName, string Email, string PhoneNumber);
|
||||
record ReceiverDraft(Guid Id, string FullName, string Email, string PhoneNumber, string Color);
|
||||
|
||||
record EditorSessionData(
|
||||
byte[] OriginalPdfBytes,
|
||||
List<SignatureFieldDraft> Fields,
|
||||
string FileName,
|
||||
List<ReceiverDraft> Receivers);
|
||||
|
||||
// ── Receiver colour palette (cycles when > 8 receivers) ──
|
||||
static readonly string[] ReceiverPalette =
|
||||
[
|
||||
"#4F46E5", // indigo
|
||||
"#059669", // emerald
|
||||
"#DC2626", // red
|
||||
"#D97706", // amber
|
||||
"#7C3AED", // violet
|
||||
"#0891B2", // cyan
|
||||
"#BE185D", // pink
|
||||
"#65A30D", // lime
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user