- Services/PdfRedactText.cs: strip text whose origin falls inside a CoverAnnotation from the page content stream at save time, hooked into PdfBurn.DrawAnnotationsIntoDoc. Fixes edited values staying recoverable by text extraction. - Themes/MMD.xaml replaces all thirteen themes; picker and accent strip removed; no dark mode. - Rename KillerPDF -> MMD PDF across code, resources, packaging and locale strings; new icon. - Remove the upstream author credit and the in-app install button.
109 lines
4.7 KiB
C#
109 lines
4.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using PdfSharpCore.Pdf;
|
|
|
|
namespace MmdPdf
|
|
{
|
|
// Read/edit the PDF Document Info dictionary (Title, Author, Subject, Keywords, Creator). Themed via
|
|
// DialogChrome, no preview pane. Producer/dates/structure are shown read-only.
|
|
internal sealed class DocumentInfoDialog : Window
|
|
{
|
|
private readonly PdfDocument _doc;
|
|
private TextBox _title = null!, _author = null!, _subject = null!, _keywords = null!, _creator = null!;
|
|
|
|
public bool Saved { get; private set; }
|
|
|
|
public DocumentInfoDialog(Window owner, PdfDocument doc, string? filePath)
|
|
{
|
|
_doc = doc;
|
|
Title = "MmdPdf - " + L("Str_DocInfo_Suffix");
|
|
Width = 460;
|
|
SizeToContent = SizeToContent.Height;
|
|
UseLayoutRounding = true;
|
|
DialogChrome.Configure(this, owner);
|
|
BuildUi(filePath);
|
|
}
|
|
|
|
private void BuildUi(string? filePath)
|
|
{
|
|
var body = new StackPanel { Margin = new Thickness(20, 6, 20, 16) };
|
|
|
|
_title = AddField(body, L("Str_DocInfo_Title"), _doc.Info.Title);
|
|
_author = AddField(body, L("Str_DocInfo_Author"), _doc.Info.Author);
|
|
_subject = AddField(body, L("Str_DocInfo_Subject"), _doc.Info.Subject);
|
|
_keywords = AddField(body, L("Str_DocInfo_Keywords"), _doc.Info.Keywords, wrap: true);
|
|
_creator = AddField(body, L("Str_DocInfo_Creator"), _doc.Info.Creator);
|
|
|
|
body.Children.Add(new TextBlock
|
|
{
|
|
Text = BuildSummary(filePath),
|
|
FontFamily = UiKit.MonoFont, FontSize = 11,
|
|
Foreground = UiKit.Brush("MutedTextBrush"),
|
|
TextWrapping = TextWrapping.Wrap,
|
|
Margin = new Thickness(0, 12, 0, 0)
|
|
});
|
|
|
|
var cancel = UiKit.Make(L("Str_DocInfo_Cancel"), accent: false);
|
|
cancel.Click += (_, _2) => { DialogResult = false; Close(); };
|
|
cancel.IsCancel = true; // Esc
|
|
var save = UiKit.Make(L("Str_DocInfo_Save"), accent: true);
|
|
save.Click += (_, _2) => SaveAndClose();
|
|
save.IsDefault = true; // Enter
|
|
var row = UiKit.ButtonRow(cancel, save);
|
|
row.Margin = new Thickness(0, 16, 0, 0);
|
|
body.Children.Add(row);
|
|
|
|
Content = DialogChrome.Frame(this, Owner, "MmdPdf - " + L("Str_DocInfo_Suffix"),
|
|
() => { DialogResult = false; Close(); }, body);
|
|
|
|
Loaded += (_, _2) => _title.Focus();
|
|
}
|
|
|
|
private static TextBox AddField(StackPanel host, string label, string? value, bool wrap = false)
|
|
{
|
|
host.Children.Add(UiKit.GroupLabel(label));
|
|
var f = UiKit.Field();
|
|
f.Text = value ?? "";
|
|
f.Margin = new Thickness(0, 0, 0, 8);
|
|
// Every field wraps and grows with its content up to a cap, then scrolls - so long titles,
|
|
// subjects, or keyword lists aren't cramped on a single line. Enter is not a newline (each value
|
|
// stays a single metadata string). The `wrap` hint just gives the long-form fields more room.
|
|
f.TextWrapping = TextWrapping.Wrap;
|
|
f.AcceptsReturn = false;
|
|
f.VerticalContentAlignment = VerticalAlignment.Top;
|
|
f.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
|
|
f.MaxHeight = wrap ? 110 : 72; // grow up to ~5 lines (keywords) / ~3 lines (others), then scroll
|
|
host.Children.Add(f);
|
|
return f;
|
|
}
|
|
|
|
private string BuildSummary(string? filePath)
|
|
{
|
|
var parts = new List<string>();
|
|
string producer = ""; try { producer = _doc.Info.Producer ?? ""; } catch { }
|
|
if (producer.Length > 0) parts.Add($"Producer: {producer}");
|
|
parts.Add($"{_doc.PageCount} pages");
|
|
parts.Add($"PDF {_doc.Version / 10}.{_doc.Version % 10}");
|
|
try { var d = _doc.Info.CreationDate; if (d != default) parts.Add($"created {d:yyyy-MM-dd HH:mm}"); } catch { }
|
|
try { if (!string.IsNullOrEmpty(filePath) && File.Exists(filePath)) parts.Add($"{new FileInfo(filePath).Length / 1024.0:N0} KB"); } catch { }
|
|
return string.Join("\n", parts);
|
|
}
|
|
|
|
private void SaveAndClose()
|
|
{
|
|
_doc.Info.Title = _title.Text;
|
|
_doc.Info.Author = _author.Text;
|
|
_doc.Info.Subject = _subject.Text;
|
|
_doc.Info.Keywords = _keywords.Text;
|
|
_doc.Info.Creator = _creator.Text;
|
|
Saved = true;
|
|
Close();
|
|
}
|
|
|
|
private static string L(string key) => Application.Current?.TryFindResource(key) as string ?? key;
|
|
}
|
|
}
|