feat: rebrand to MMD PDF, single corporate theme, and remove original text under an edit
- 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.
This commit is contained in:
+6
-6
@@ -3,9 +3,9 @@ using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using KillerPDF.Features;
|
||||
using MmdPdf.Features;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
/// <summary>
|
||||
/// The About overlay's window half: the IAboutHost implementation that maps the controller's
|
||||
@@ -13,9 +13,9 @@ namespace KillerPDF
|
||||
/// handlers. All the logic - signature, hashing, update check, self-update - lives in
|
||||
/// <see cref="AboutController"/>.
|
||||
///
|
||||
/// NOTE: this stays "namespace KillerPDF" rather than KillerPDF.Shell, because it is a partial
|
||||
/// NOTE: this stays "namespace MmdPdf" rather than MmdPdf.Shell, because it is a partial
|
||||
/// of MainWindow and every partial of a class must share one namespace. It moves to
|
||||
/// KillerPDF.Shell when MainWindow itself does.
|
||||
/// MmdPdf.Shell when MainWindow itself does.
|
||||
/// </summary>
|
||||
public partial class MainWindow : IAboutHost
|
||||
{
|
||||
@@ -123,7 +123,7 @@ namespace KillerPDF
|
||||
FontSize = 27.3,
|
||||
Foreground = Res("AccentLogo")
|
||||
});
|
||||
hl.Click += (_, _) => AboutController.OpenUrl("https://killerpdf.net");
|
||||
hl.Click += (_, _) => AboutController.OpenUrl("https://baobab-ts.com");
|
||||
AboutLogoBlock.Inlines.Add(hl);
|
||||
|
||||
// The shadow copy mirrors the real runs exactly (sizes, weights, fonts), so the blur
|
||||
@@ -176,7 +176,7 @@ namespace KillerPDF
|
||||
|
||||
AddText(pre);
|
||||
AboutTaglineBlock.Inlines.Add(
|
||||
AccentLink("Killer Tools", () => AboutController.OpenUrl("https://killertools.net")));
|
||||
AccentLink("Killer Tools", () => AboutController.OpenUrl("https://baobab-ts.com")));
|
||||
AddText(suf);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
// App-wide accessibility size, ported from KillerNotes: a LayoutTransform scale on the
|
||||
// chrome (toolbar row, sidebar, tab strip) grows or shrinks the UI crisply -
|
||||
|
||||
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -318,7 +318,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_DuplicateFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_DuplicateFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -140,7 +140,7 @@ namespace KillerPDF
|
||||
private static void HideBusyOverlay(Border overlay)
|
||||
=> (overlay.Parent as Panel)?.Children.Remove(overlay);
|
||||
|
||||
// RenderToPng lives in Services/BitmapHelpers.cs (KillerUI refactor), with the other
|
||||
// RenderToPng lives in Services/BitmapHelpers.cs (MmdPdfUI refactor), with the other
|
||||
// raw-bitmap helpers.
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -17,10 +17,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -154,7 +154,7 @@ namespace KillerPDF
|
||||
{
|
||||
var ask = KillerDialog.Show(this,
|
||||
string.Format(Loc("Str_Dlg_RepairAsk"), System.IO.Path.GetFileName(path)),
|
||||
"KillerPDF", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
"MmdPdf", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
if (ask != MessageBoxResult.Yes) return null;
|
||||
|
||||
var busy = ShowBusyOverlay(Loc("Str_Busy_Repairing"));
|
||||
@@ -174,7 +174,7 @@ namespace KillerPDF
|
||||
if (repaired is null)
|
||||
KillerDialog.Show(this,
|
||||
$"\"{System.IO.Path.GetFileName(path)}\" could not be repaired.",
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return repaired;
|
||||
}
|
||||
finally { HideBusyOverlay(busy); }
|
||||
|
||||
@@ -2,9 +2,9 @@ using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
/// <summary>
|
||||
/// Single-instance entry points: App forwards a second launch's file path here rather than
|
||||
@@ -88,8 +88,8 @@ namespace KillerPDF
|
||||
{
|
||||
try { File.Delete(temp); } catch { }
|
||||
KillerDialog.Show(this,
|
||||
$"KillerPDF could not open the browser PDF.\n\n{ex.Message}",
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
$"MmdPdf could not open the browser PDF.\n\n{ex.Message}",
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-32
@@ -16,13 +16,13 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
// CliParsePageRange moved out with the CLI runner but is used here too (Export Images'
|
||||
// range box); its encoder sibling is now Services/BitmapHelpers.EncodeJpeg.
|
||||
using static KillerPDF.Features.CliRunner;
|
||||
using static MmdPdf.Features.CliRunner;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -123,14 +123,14 @@ namespace KillerPDF
|
||||
SetStatus(string.Format(Loc("Str_OpenedReadOnlyXRef"), System.IO.Path.GetFileName(path), _doc.PageCount));
|
||||
KillerDialog.Show(this,
|
||||
$"\"{System.IO.Path.GetFileName(path)}\" has a non-standard structure and was opened read-only.\n\nEditing, saving, and some other features may not work correctly.",
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ReadOnly also failed - offer to repair.
|
||||
var result = KillerDialog.Show(this,
|
||||
$"This PDF has a damaged structure and couldn't be opened.\n\nWould you like KillerPDF to attempt a repair? A repaired copy will be created - the original file will not be changed.\n\nNote: repaired files may be missing bookmarks, forms, and other interactive features.",
|
||||
"KillerPDF", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
$"This PDF has a damaged structure and couldn't be opened.\n\nWould you like MmdPdf to attempt a repair? A repaired copy will be created - the original file will not be changed.\n\nNote: repaired files may be missing bookmarks, forms, and other interactive features.",
|
||||
"MmdPdf", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
if (result == MessageBoxResult.Yes)
|
||||
TryRepairAndOpen(srcPath);
|
||||
}
|
||||
@@ -150,8 +150,8 @@ namespace KillerPDF
|
||||
// we can't classify the damage, but the PDFium-based repair often recovers it anyway, so
|
||||
// offer the repair rather than just failing outright.
|
||||
var result = KillerDialog.Show(this,
|
||||
"This PDF couldn't be opened - its structure may be damaged.\n\nWould you like KillerPDF to attempt a repair? A repaired copy will be created - the original file will not be changed.\n\nNote: repaired files may be missing bookmarks, forms, and other interactive features.",
|
||||
"KillerPDF", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
"This PDF couldn't be opened - its structure may be damaged.\n\nWould you like MmdPdf to attempt a repair? A repaired copy will be created - the original file will not be changed.\n\nNote: repaired files may be missing bookmarks, forms, and other interactive features.",
|
||||
"MmdPdf", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
if (result == MessageBoxResult.Yes)
|
||||
TryRepairAndOpen(srcPath); // sets _asyncOpenPending and finalizes the tab itself
|
||||
}
|
||||
@@ -213,7 +213,7 @@ namespace KillerPDF
|
||||
// Themed "Password Required" prompt (KillerDialog): family dialog chrome + themed PasswordBox.
|
||||
private string? PromptForPassword(string filename) => KillerDialog.PromptPassword(this, filename);
|
||||
|
||||
// ALL direct PDFium P/Invoke lives in Services/PdfiumInterop.cs (KillerUI refactor) -
|
||||
// ALL direct PDFium P/Invoke lives in Services/PdfiumInterop.cs (MmdPdfUI refactor) -
|
||||
// one class, one lock (Docnet's), so the thread-safety discipline stays auditable.
|
||||
// PdfFileHasEncryption and TryImportRepairToPath live in Services/PdfImport.cs.
|
||||
|
||||
@@ -234,7 +234,7 @@ namespace KillerPDF
|
||||
bool raster = false;
|
||||
|
||||
// Strategy 0 (#103): lossless PDFium re-save. PDFium's tolerant parser recovers
|
||||
// broken xref tables (including the dangling /Outlines entry older KillerPDF
|
||||
// broken xref tables (including the dangling /Outlines entry older MmdPdf
|
||||
// builds wrote) and rewrites a clean file preserving EVERYTHING - forms,
|
||||
// bookmarks, text. The import-copy below drops the document-level AcroForm,
|
||||
// which is what used to turn a repaired fillable form into a flat one.
|
||||
@@ -267,7 +267,7 @@ namespace KillerPDF
|
||||
_asyncOpenPending = false;
|
||||
KillerDialog.Show(this,
|
||||
"Repair failed - the file is too severely damaged to recover.\n\nTry opening the original in a different application (Adobe Acrobat, browsers) which may have additional recovery options.",
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -284,13 +284,13 @@ namespace KillerPDF
|
||||
raster
|
||||
? string.Format(Loc("Str_Dlg_RepairedRaster"), System.IO.Path.GetFileName(path))
|
||||
: string.Format(Loc("Str_Dlg_Repaired"), System.IO.Path.GetFileName(path)),
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.None);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.None);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
HideBusyOverlay(busy);
|
||||
_asyncOpenPending = false;
|
||||
KillerDialog.Show(this, Loc("Str_Err_RepairFailed") + "\n" + ex.Message, "KillerPDF",
|
||||
KillerDialog.Show(this, Loc("Str_Err_RepairFailed") + "\n" + ex.Message, "MmdPdf",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
@@ -333,7 +333,7 @@ namespace KillerPDF
|
||||
HideBusyOverlay(busy);
|
||||
_asyncOpenPending = false;
|
||||
KillerDialog.Show(this, Loc("Str_Err_OpenProtected") + "\n" + ex.Message,
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
EndCancellableOp();
|
||||
}
|
||||
}
|
||||
@@ -363,7 +363,7 @@ namespace KillerPDF
|
||||
{
|
||||
var res = KillerDialog.Show(this,
|
||||
Loc("Str_Dlg_UnsavedClose"),
|
||||
"KillerPDF", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
"MmdPdf", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
if (res != MessageBoxResult.Yes) return;
|
||||
}
|
||||
_doc.Close();
|
||||
@@ -445,7 +445,7 @@ namespace KillerPDF
|
||||
{
|
||||
AbortTabLoad(target, prev, createdNew);
|
||||
KillerDialog.Show(this, Loc("Str_Err_NewDocFailed") + "\n" + ex.Message,
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,7 +478,7 @@ namespace KillerPDF
|
||||
var item = MakeMenuItem(System.IO.Path.GetFileName(path), (_, _) =>
|
||||
{
|
||||
if (System.IO.File.Exists(path)) OpenInNewTab(path);
|
||||
else KillerDialog.Show(this, Loc("Str_Err_FileNotFound") + "\n" + path, "KillerPDF",
|
||||
else KillerDialog.Show(this, Loc("Str_Err_FileNotFound") + "\n" + path, "MmdPdf",
|
||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
});
|
||||
item.ToolTip = path;
|
||||
@@ -562,7 +562,7 @@ namespace KillerPDF
|
||||
}
|
||||
|
||||
// The file-type icon lookup (per-extension cache + SHGetFileInfo) lives in
|
||||
// Services/ShellIcons.cs - the same shape the KillerUI file picker uses.
|
||||
// Services/ShellIcons.cs - the same shape the MmdPdfUI file picker uses.
|
||||
|
||||
// Fills the empty-state "Recent" list with clickable filenames (hidden when there are none).
|
||||
// The start screen belongs to a PANE, so a pane filling its own list has to name itself: the
|
||||
@@ -714,7 +714,7 @@ namespace KillerPDF
|
||||
// through ActiveViewer. Clicking pane B's recents opened the file in pane A.
|
||||
FocusPane(pane);
|
||||
if (System.IO.File.Exists(path)) OpenInNewTab(path);
|
||||
else KillerDialog.Show(this, Loc("Str_Err_FileNotFound") + "\n" + path, "KillerPDF",
|
||||
else KillerDialog.Show(this, Loc("Str_Err_FileNotFound") + "\n" + path, "MmdPdf",
|
||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
};
|
||||
list.Items.Add(row);
|
||||
@@ -800,15 +800,15 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_MergeFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_MergeFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// The named-destination helpers (BuildNamedDestMap, RewriteNamedDestLinks and their
|
||||
// private walkers) live in Services/PdfImport.cs (KillerUI refactor).
|
||||
// private walkers) live in Services/PdfImport.cs (MmdPdfUI refactor).
|
||||
|
||||
// DerefItemStatic, RectNum and the pre-save scrubs live in Services/PdfScrub.cs
|
||||
// (KillerUI refactor) - pure functions shared by the GUI saves, TempReload and the CLI.
|
||||
// (MmdPdfUI refactor) - pure functions shared by the GUI saves, TempReload and the CLI.
|
||||
|
||||
// ============================================================
|
||||
// Adobe page-size guard
|
||||
@@ -817,8 +817,8 @@ namespace KillerPDF
|
||||
// Adobe Reader only displays pages whose sides are 3-14400 points; anything outside
|
||||
// that range shows "The dimensions of this page are out-of-range" and renders blank.
|
||||
// Such pages usually come from images with broken DPI metadata turned into a PDF (by
|
||||
// KillerPDF 1.6.1 and earlier, or by other tools). PDFium renders any size, so the
|
||||
// file looks normal in KillerPDF and only fails in Adobe.
|
||||
// MmdPdf 1.6.1 and earlier, or by other tools). PDFium renders any size, so the
|
||||
// file looks normal in MmdPdf and only fails in Adobe.
|
||||
// Min/MaxAdobePageDim live in Services/PdfImport.cs (shared with the image importer).
|
||||
|
||||
private static bool PageOutOfAdobeRange(PdfPage p)
|
||||
@@ -838,7 +838,7 @@ namespace KillerPDF
|
||||
if (PageOutOfAdobeRange(_doc.Pages[i])) bad++;
|
||||
if (bad == 0) return;
|
||||
var res = KillerDialog.Show(this, string.Format(Loc("Str_Dlg_PageOutOfRange"), bad),
|
||||
"KillerPDF", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
"MmdPdf", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
if (res != MessageBoxResult.Yes) return;
|
||||
for (int i = 0; i < _doc.PageCount; i++)
|
||||
if (PageOutOfAdobeRange(_doc.Pages[i]))
|
||||
@@ -971,7 +971,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_SaveFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_SaveFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1088,7 +1088,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_SaveFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_SaveFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1171,7 +1171,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
try { KillerDialog.Show(this, Loc("Str_Err_FlattenFailed") + "\n" + ex.GetType().Name + ": " + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error); }
|
||||
try { KillerDialog.Show(this, Loc("Str_Err_FlattenFailed") + "\n" + ex.GetType().Name + ": " + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error); }
|
||||
catch { /* dialog failed; overlay still removed in finally */ }
|
||||
}
|
||||
finally
|
||||
@@ -1207,7 +1207,7 @@ namespace KillerPDF
|
||||
if (selected is null)
|
||||
{
|
||||
KillerDialog.Show(this, rangeErr.Length > 0 ? rangeErr : Loc("Str_InvalidRange"),
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1284,7 +1284,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_ExportFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_ExportFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -1430,7 +1430,7 @@ namespace KillerPDF
|
||||
|
||||
// Open the preview window immediately. Pages rasterize on a background thread and
|
||||
// stream in via SetRenderedPage, so the window appears at once and the app stays
|
||||
// responsive on large files. WPF's OS PrintDialog can't show a preview, so KillerPDF
|
||||
// responsive on large files. WPF's OS PrintDialog can't show a preview, so MmdPdf
|
||||
// renders it and drives printing itself.
|
||||
string renderPath = printPath;
|
||||
string? cleanup = tempFlattened;
|
||||
@@ -1481,7 +1481,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
try { KillerDialog.Show(this, Loc("Str_Err_PrintFailed") + "\n" + ex.GetType().Name + ": " + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error); }
|
||||
try { KillerDialog.Show(this, Loc("Str_Err_PrintFailed") + "\n" + ex.GetType().Name + ": " + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error); }
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -131,7 +131,7 @@ namespace KillerPDF
|
||||
|
||||
var b = CurrentMonitorBoundsDip();
|
||||
Topmost = true;
|
||||
// #215: Topmost exists only to cover the always-on-top taskbar while KillerPDF is
|
||||
// #215: Topmost exists only to cover the always-on-top taskbar while MmdPdf is
|
||||
// the ACTIVE window. Held unconditionally, it sat over every other program the user
|
||||
// switched to. Yield it on deactivate, take it back on return - browser behavior.
|
||||
Deactivated += FsYieldTopmost;
|
||||
|
||||
+12
-12
@@ -10,9 +10,9 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
// Import images as a PDF, and compress the current PDF to a .zip. Kept in its own partial-class
|
||||
// file rather than the MainWindow monolith. User-facing strings go through Loc() (keys live in
|
||||
@@ -51,7 +51,7 @@ namespace KillerPDF
|
||||
{
|
||||
AbortTabLoad(target, prev, createdNew);
|
||||
KillerDialog.Show(this, Loc("Str_Err_ImportFailed") + "\n" + ex.Message,
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace KillerPDF
|
||||
return outPath;
|
||||
}
|
||||
|
||||
// AddImagePagesFromFile and IsPdfPath live in Services/PdfImport.cs (KillerUI refactor).
|
||||
// AddImagePagesFromFile and IsPdfPath live in Services/PdfImport.cs (MmdPdfUI refactor).
|
||||
|
||||
// ----- Drag/drop of folders, archives, and multiple files ----------------------------
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace KillerPDF
|
||||
{
|
||||
CleanupDirs(tempDirs);
|
||||
KillerDialog.Show(this, Loc("Str_Err_ImportFailed") + "\n" + ex.Message,
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace KillerPDF
|
||||
{
|
||||
var proceed = KillerDialog.Show(this,
|
||||
string.Format(Loc("Str_Drop_TooMany"), found.Count, MaxDropFiles),
|
||||
"KillerPDF", MessageBoxButton.OKCancel);
|
||||
"MmdPdf", MessageBoxButton.OKCancel);
|
||||
if (proceed != MessageBoxResult.OK) { CleanupDirs(tempDirs); return; }
|
||||
found = found.GetRange(0, MaxDropFiles);
|
||||
}
|
||||
@@ -164,7 +164,7 @@ namespace KillerPDF
|
||||
if (found.Count > 30)
|
||||
{
|
||||
var ok = KillerDialog.Show(this, string.Format(Loc("Str_Drop_ManyTabs"), found.Count),
|
||||
"KillerPDF", MessageBoxButton.OKCancel);
|
||||
"MmdPdf", MessageBoxButton.OKCancel);
|
||||
if (ok != MessageBoxResult.OK) return;
|
||||
}
|
||||
foreach (var f in found)
|
||||
@@ -207,7 +207,7 @@ namespace KillerPDF
|
||||
HideBusyOverlay(busy);
|
||||
AbortTabLoad(target, prev, createdNew);
|
||||
KillerDialog.Show(this, Loc("Str_Err_ImportFailed") + "\n" + ex.Message,
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -235,7 +235,7 @@ namespace KillerPDF
|
||||
{
|
||||
AbortTabLoad(target, prev, createdNew);
|
||||
KillerDialog.Show(this, Loc("Str_Err_ImportFailed") + "\n" + ex.Message,
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ namespace KillerPDF
|
||||
|
||||
private static string? ExtractZipToTemp(string zipPath)
|
||||
{
|
||||
string dir = Path.Combine(Path.GetTempPath(), "KillerPDF-zip-" + Guid.NewGuid().ToString("N")[..8]);
|
||||
string dir = Path.Combine(Path.GetTempPath(), "MmdPdf-zip-" + Guid.NewGuid().ToString("N")[..8]);
|
||||
try { Directory.CreateDirectory(dir); ZipFile.ExtractToDirectory(zipPath, dir); return dir; }
|
||||
catch { try { Directory.Delete(dir, true); } catch { } return null; }
|
||||
}
|
||||
@@ -305,7 +305,7 @@ namespace KillerPDF
|
||||
if (_isDirty || string.IsNullOrEmpty(_originalFile) || !File.Exists(_originalFile))
|
||||
{
|
||||
var ask = KillerDialog.Show(this, Loc("Str_Dlg_SaveBeforeZip"),
|
||||
"KillerPDF", MessageBoxButton.OKCancel);
|
||||
"MmdPdf", MessageBoxButton.OKCancel);
|
||||
if (ask != MessageBoxResult.OK) return;
|
||||
SaveInPlace();
|
||||
if (_isDirty || string.IsNullOrEmpty(_originalFile) || !File.Exists(_originalFile))
|
||||
@@ -337,7 +337,7 @@ namespace KillerPDF
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_ZipFailed") + "\n" + ex.Message,
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
// ============================================================
|
||||
// Visual keyboard for the shortcuts overlay.
|
||||
@@ -19,7 +19,7 @@ namespace KillerPDF
|
||||
public partial class MainWindow
|
||||
{
|
||||
// KbLayer, the binding table and its types live in Services/ShortcutTable.cs, which is free
|
||||
// of WPF so KillerPDF.Tests can link it.
|
||||
// of WPF so MmdPdf.Tests can link it.
|
||||
private KbLayer _kbLayer = KbLayer.Base;
|
||||
private bool _kbBuilt;
|
||||
private TextBlock? _kbDetail;
|
||||
@@ -187,7 +187,7 @@ namespace KillerPDF
|
||||
key.SetResourceReference(Border.CornerRadiusProperty, "ControlCornerRadius");
|
||||
key.SetResourceReference(Border.BackgroundProperty, "KeyboardKeyBrush");
|
||||
key.SetResourceReference(Border.BorderBrushProperty, "CardBorderBrush");
|
||||
// Hover: the keycap lifts a few pixels, like the cards on the killertools.net front page.
|
||||
// Hover: the keycap lifts a few pixels, like the cards on the baobab-ts.com front page.
|
||||
var lift = new TranslateTransform();
|
||||
key.RenderTransform = lift;
|
||||
string keyId = id;
|
||||
|
||||
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -147,7 +147,7 @@ namespace KillerPDF
|
||||
{
|
||||
// A cancellable long operation (OCR, repair) is running behind the busy overlay - offer to
|
||||
// cancel it instead of letting Escape fall through to the app-exit handler below.
|
||||
if (KillerDialog.Show(this, string.Format(Loc("Str_Dlg_CancelBusy"), _busyOpLabel), "KillerPDF",
|
||||
if (KillerDialog.Show(this, string.Format(Loc("Str_Dlg_CancelBusy"), _busyOpLabel), "MmdPdf",
|
||||
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
|
||||
_busyCts?.Cancel();
|
||||
e.Handled = true;
|
||||
@@ -698,7 +698,7 @@ namespace KillerPDF
|
||||
// Opens the online help / how-to page in the user's default browser.
|
||||
private void OnlineHelp_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try { Process.Start(new ProcessStartInfo("https://killerpdf.net/help.html") { UseShellExecute = true }); }
|
||||
try { Process.Start(new ProcessStartInfo("https://baobab-ts.com/help.html") { UseShellExecute = true }); }
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -4,10 +4,10 @@ using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using KillerPDF.Features;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Features;
|
||||
using MmdPdf.Services;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow : IOcrHost
|
||||
{
|
||||
@@ -193,13 +193,13 @@ namespace KillerPDF
|
||||
OcrLanguages.TryDeleteFile(dest + ".part");
|
||||
if (ct.IsCancellationRequested) SetStatus(string.Format(Loc("Str_St_LangCanceled"), name));
|
||||
else KillerDialog.Show(this, string.Format(Loc("Str_Dlg_DownloadTimeout"), name),
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
HideBusyOverlay(busy);
|
||||
OcrLanguages.TryDeleteFile(dest + ".part");
|
||||
KillerDialog.Show(this, string.Format(Loc("Str_Err_LangDataFailed"), name) + "\n" + ex.Message, "KillerPDF",
|
||||
KillerDialog.Show(this, string.Format(Loc("Str_Err_LangDataFailed"), name) + "\n" + ex.Message, "MmdPdf",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
@@ -266,7 +266,7 @@ namespace KillerPDF
|
||||
catch (Exception ex)
|
||||
{
|
||||
HideBusyOverlay(busy);
|
||||
KillerDialog.Show(this, Loc("Str_Err_HqDownloadFailed") + "\n" + ex.Message, "KillerPDF",
|
||||
KillerDialog.Show(this, Loc("Str_Err_HqDownloadFailed") + "\n" + ex.Message, "MmdPdf",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
@@ -292,7 +292,7 @@ namespace KillerPDF
|
||||
string names = string.Join(", ", missing.ConvertAll(OcrLanguages.NameForCode));
|
||||
var choice = KillerDialog.Show(this,
|
||||
string.Format(Loc("Str_Dlg_LangDownloadAsk"), names),
|
||||
"KillerPDF", MessageBoxButton.OKCancel, MessageBoxImage.Information);
|
||||
"MmdPdf", MessageBoxButton.OKCancel, MessageBoxImage.Information);
|
||||
if (choice != MessageBoxResult.OK) return false;
|
||||
|
||||
var ct = BeginCancellableOp(Loc("Str_Op_LangDownload"));
|
||||
@@ -325,7 +325,7 @@ namespace KillerPDF
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_ModelDownloadFailed") + "\n" + ex.Message,
|
||||
"KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
"MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
|
||||
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -81,7 +81,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_SplitFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_SplitFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace KillerPDF
|
||||
var doc = _doc;
|
||||
var selected = PageList.SelectedItems;
|
||||
if (selected.Count == 0) { KillerDialog.Show(this, Loc("Str_Dlg_SelectDelete")); return; }
|
||||
var result = KillerDialog.Show(this, selected.Count == 1 ? Loc("Str_Dlg_DeletePage1") : string.Format(Loc("Str_Dlg_DeletePagesN"), selected.Count), "KillerPDF",
|
||||
var result = KillerDialog.Show(this, selected.Count == 1 ? Loc("Str_Dlg_DeletePage1") : string.Format(Loc("Str_Dlg_DeletePagesN"), selected.Count), "MmdPdf",
|
||||
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
if (result != MessageBoxResult.Yes) return;
|
||||
try
|
||||
@@ -105,7 +105,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_DeleteFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_DeleteFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_InsertFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_InsertFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_AddPageFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_AddPageFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -2,9 +2,9 @@ using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using KillerPDF.Controls;
|
||||
using MmdPdf.Controls;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
/// <summary>
|
||||
/// Moving a document tab from one pane to the other. Partial of MainWindow.
|
||||
|
||||
+3
-23
@@ -3,7 +3,7 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media.Animation;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
/// <summary>
|
||||
/// The rail's flyout buttons (family order, locked 2026-07-30: app-specific toggles, then
|
||||
@@ -20,7 +20,6 @@ namespace KillerPDF
|
||||
|
||||
private void RailLang_Click(object sender, RoutedEventArgs e) => ToggleRailFlyout(LangFlyout);
|
||||
|
||||
private void RailTheme_Click(object sender, RoutedEventArgs e) => ToggleRailFlyout(ThemeFlyout);
|
||||
|
||||
private void RailView_Click(object sender, RoutedEventArgs e) => ToggleRailFlyout(ViewFlyout);
|
||||
|
||||
@@ -49,14 +48,14 @@ namespace KillerPDF
|
||||
SyncPickerState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void ToggleRailFlyout(ContextMenu menu)
|
||||
{
|
||||
if (menu.IsOpen) { menu.IsOpen = false; return; }
|
||||
|
||||
// The theme strip always faces the document. Mirroring the two columns also makes its
|
||||
// width animation grow outward from the rail on either side of the window.
|
||||
if (menu == ThemeFlyout)
|
||||
SyncThemeFlyoutSide();
|
||||
|
||||
// Radios and accent dots reflect live state before the card shows - the same single
|
||||
// sync the Settings panel runs on open.
|
||||
@@ -79,24 +78,5 @@ namespace KillerPDF
|
||||
EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut }
|
||||
});
|
||||
}
|
||||
|
||||
private void SyncThemeFlyoutSide()
|
||||
{
|
||||
if (ThemePickerLayout is null || ThemeSubmenu is null || AccentStripHost is null ||
|
||||
AccentStripDivider is null || AccentStrip is null)
|
||||
return;
|
||||
|
||||
Grid.SetColumn(ThemeSubmenu, _sidebarRight ? 1 : 0);
|
||||
Grid.SetColumn(AccentStripHost, _sidebarRight ? 0 : 1);
|
||||
AccentStripDivider.HorizontalAlignment = _sidebarRight
|
||||
? HorizontalAlignment.Right
|
||||
: HorizontalAlignment.Left;
|
||||
AccentStrip.Margin = _sidebarRight
|
||||
? new Thickness(2, 6, 7, 6)
|
||||
: new Thickness(7, 6, 2, 6);
|
||||
ThemePickerLayout.Margin = _sidebarRight
|
||||
? new Thickness(3, 10, 12, 10)
|
||||
: new Thickness(12, 10, 3, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -9,9 +9,9 @@ using Docnet.Core.Models;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -150,7 +150,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, string.Format(Loc("Str_Tf_Failed"), ex.Message), "KillerPDF",
|
||||
KillerDialog.Show(this, string.Format(Loc("Str_Tf_Failed"), ex.Message), "MmdPdf",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -16,11 +16,11 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Features;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Features;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow : ISearchHost
|
||||
{
|
||||
|
||||
+64
-212
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -31,48 +31,6 @@ namespace KillerPDF
|
||||
|
||||
// Syncs every picker's radios and accent dots to live state before a flyout shows -
|
||||
// exactly ONE sync implementation, shared by all the rail flyouts (Shell/RailFlyouts.cs).
|
||||
private void SyncPickerState()
|
||||
{
|
||||
var cur = ThemeManager.Current;
|
||||
ThemeDarkRadio.IsChecked = cur == Theme.Dark;
|
||||
ThemeLightRadio.IsChecked = cur == Theme.Light;
|
||||
ThemeHCRadio.IsChecked = cur == Theme.Black;
|
||||
Theme98SERadio.IsChecked = cur == Theme.SE98;
|
||||
ThemeBloodRadio.IsChecked = cur == Theme.Blood;
|
||||
ThemeGreedRadio.IsChecked = cur == Theme.Greed;
|
||||
ThemeCyanoticRadio.IsChecked = cur == Theme.Cyanotic;
|
||||
ThemeEctoplasmRadio.IsChecked = cur == Theme.Ectoplasm;
|
||||
ThemeDecayRadio.IsChecked = cur == Theme.Decay;
|
||||
ThemeMourningRadio.IsChecked = cur == Theme.Mourning;
|
||||
ThemeSepulchreRadio.IsChecked = cur == Theme.Sepulchre;
|
||||
ThemeDeliriumRadio.IsChecked = cur == Theme.Delirium;
|
||||
ThemeMalaiseRadio.IsChecked = cur == Theme.Malaise;
|
||||
UpdateAccentStrip(animate: false);
|
||||
// Sync language picker
|
||||
var curLoc = KillerPDF.Services.LocaleManager.Current;
|
||||
LangEnRadio.IsChecked = curLoc == KillerPDF.Services.Locale.EnUS;
|
||||
LangCsRadio.IsChecked = curLoc == KillerPDF.Services.Locale.CsCZ;
|
||||
LangEsRadio.IsChecked = curLoc == KillerPDF.Services.Locale.Es;
|
||||
LangFrRadio.IsChecked = curLoc == KillerPDF.Services.Locale.Fr;
|
||||
LangZhTWRadio.IsChecked = curLoc == KillerPDF.Services.Locale.ZhTW;
|
||||
LangZhCNRadio.IsChecked = curLoc == KillerPDF.Services.Locale.ZhCN;
|
||||
LangBnRadio.IsChecked = curLoc == KillerPDF.Services.Locale.Bn;
|
||||
LangTrRadio.IsChecked = curLoc == KillerPDF.Services.Locale.TrTR;
|
||||
LangDeRadio.IsChecked = curLoc == KillerPDF.Services.Locale.De;
|
||||
LangJaRadio.IsChecked = curLoc == KillerPDF.Services.Locale.JaJP;
|
||||
LangPlRadio.IsChecked = curLoc == KillerPDF.Services.Locale.PlPL;
|
||||
LangHuRadio.IsChecked = curLoc == KillerPDF.Services.Locale.HuHU;
|
||||
// Sync view mode radios. Against the PENDING mode while a fade-wrapped switch is in
|
||||
// flight (_viewMode lags until the fade-out lands), so wheel-cycling with the flyout
|
||||
// open moves the checkmark in step instead of one notch behind.
|
||||
var vm = _pendingViewMode ?? _viewMode;
|
||||
ViewSingleRadio.IsChecked = vm == ViewMode.Single;
|
||||
ViewContinuousRadio.IsChecked = vm == ViewMode.Continuous;
|
||||
ViewTwoPageRadio.IsChecked = vm == ViewMode.TwoPage;
|
||||
ViewGridRadio.IsChecked = vm == ViewMode.Grid;
|
||||
// (The toolbar picker lives on the toolbar's own right-click menu, and the sidebar
|
||||
// side on the sidebar's - both build their checks fresh on open, nothing to sync here.)
|
||||
}
|
||||
|
||||
// ── Quick fade in/out for the full-window overlay panels (Shortcuts/About) ──
|
||||
private static void FadeOverlayIn(UIElement el)
|
||||
@@ -340,176 +298,41 @@ namespace KillerPDF
|
||||
RefreshOpenAnnotationBars();
|
||||
}
|
||||
|
||||
private void ThemeDarkRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Dark);
|
||||
private void ThemeLightRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Light);
|
||||
private void ThemeHCRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Black);
|
||||
private void Theme98SERadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.SE98);
|
||||
private void ThemeBloodRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Blood);
|
||||
private void ThemeGreedRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Greed);
|
||||
private void ThemeCyanoticRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Cyanotic);
|
||||
private void ThemeEctoplasmRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Ectoplasm);
|
||||
private void ThemeDecayRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Decay);
|
||||
private void ThemeMourningRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Mourning);
|
||||
private void ThemeSepulchreRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Sepulchre);
|
||||
private void ThemeDeliriumRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Delirium);
|
||||
private void ThemeMalaiseRadio_Checked(object sender, RoutedEventArgs e) => SelectTheme(Theme.Malaise);
|
||||
|
||||
private void SelectTheme(Theme theme)
|
||||
{
|
||||
bool wasOpen = ThemeFlyout is not null && ThemeFlyout.IsOpen;
|
||||
ThemeManager.Apply(theme);
|
||||
UpdateAccentStrip(animate: true);
|
||||
// Intentionally leave the flyout open so the user can try another theme right away
|
||||
// without reopening the submenu. The theme swap's side effects (tab strip rebuild,
|
||||
// tool re-select) can still knock the popup closed behind our back, so check once
|
||||
// layout has settled and quietly reopen it in place if that happened.
|
||||
if (wasOpen)
|
||||
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background,
|
||||
(Action)(() => { if (ThemeFlyout is not null && !ThemeFlyout.IsOpen) ThemeFlyout.IsOpen = true; }));
|
||||
}
|
||||
|
||||
// #199 (Ryokoxx's design): ONE vertical strip of six swatches beside the theme list,
|
||||
// repainted per family, instead of a row under each accented theme. The list height is
|
||||
// identical for every theme, so the bottom-pinned card never moves; only the strip's
|
||||
// width animates, growing rightward from the pinned left edge. Per-family accent memory
|
||||
// in ThemeManager is untouched.
|
||||
private void AccentStripDot_Click(object sender, MouseButtonEventArgs e) => HandleAccentDot(sender, _stripFamily);
|
||||
|
||||
private void HandleAccentDot(object sender, Theme family)
|
||||
{
|
||||
if (sender is not FrameworkElement fe || fe.Tag is not string tag) return;
|
||||
if (!Enum.TryParse<DarkAccent>(tag, out var accent)) return;
|
||||
ThemeManager.ApplyAccent(family, accent); // persists for that family; reapplies if active
|
||||
RingAccentStrip();
|
||||
}
|
||||
|
||||
// Per-family swatch colors, in each family's display order (moved here from the four
|
||||
// retired XAML accent rows; the strip repaints these onto its six shared dots).
|
||||
private static readonly (DarkAccent Accent, string Hex)[] DarkStripColors =
|
||||
[(DarkAccent.Red, "#DD504B"), (DarkAccent.Orange, "#E8962C"), (DarkAccent.Green, "#1EA54C"),
|
||||
(DarkAccent.Teal, "#1FB8A8"), (DarkAccent.Blue, "#4580D9"), (DarkAccent.Purple, "#B982E3")];
|
||||
private static readonly (DarkAccent Accent, string Hex)[] LightStripColors =
|
||||
[(DarkAccent.Red, "#931A1A"), (DarkAccent.Orange, "#C7710F"), (DarkAccent.Green, "#1B5E20"),
|
||||
(DarkAccent.Teal, "#0D827E"), (DarkAccent.Blue, "#18608E"), (DarkAccent.Purple, "#5A1690")];
|
||||
private static readonly (DarkAccent Accent, string Hex)[] BlackStripColors =
|
||||
[(DarkAccent.Red, "#FF2929"), (DarkAccent.Orange, "#FF910A"), (DarkAccent.Green, "#00FF66"),
|
||||
(DarkAccent.Teal, "#0AFFE7"), (DarkAccent.Blue, "#298DFF"), (DarkAccent.Purple, "#B829FF")];
|
||||
private static readonly (DarkAccent Accent, string Hex)[] SE98StripColors =
|
||||
[(DarkAccent.Red, "#800040"), (DarkAccent.Orange, "#A05000"), (DarkAccent.Green, "#006000"),
|
||||
(DarkAccent.Teal, "#008080"), (DarkAccent.Blue, "#000080"), (DarkAccent.Purple, "#5A376E")];
|
||||
private static readonly (DarkAccent Accent, string Hex)[] DarkStripColors = [];
|
||||
private static readonly (DarkAccent Accent, string Hex)[] LightStripColors = [];
|
||||
private static readonly (DarkAccent Accent, string Hex)[] BlackStripColors = [];
|
||||
private static readonly (DarkAccent Accent, string Hex)[] SE98StripColors = [];
|
||||
|
||||
private static (DarkAccent Accent, string Hex)[] StripColorsFor(Theme family) => family switch
|
||||
{
|
||||
Theme.Light => LightStripColors,
|
||||
Theme.Black => BlackStripColors,
|
||||
Theme.SE98 => SE98StripColors,
|
||||
_ => DarkStripColors,
|
||||
};
|
||||
|
||||
private Theme _stripFamily = Theme.Dark; // the family the strip's dots currently show
|
||||
private bool _stripOpen;
|
||||
private const double AccentStripWidth = 39; // 1px rule + 10 gap + 26 swatch + 2 air
|
||||
private const double AccentStripSlideMs = 180;
|
||||
|
||||
private Border[] StripDots =>
|
||||
[AccentStripDot0, AccentStripDot1, AccentStripDot2, AccentStripDot3, AccentStripDot4, AccentStripDot5];
|
||||
|
||||
private void PopulateAccentStrip(Theme family)
|
||||
{
|
||||
var colors = StripColorsFor(family);
|
||||
var dots = StripDots;
|
||||
for (int i = 0; i < dots.Length; i++)
|
||||
{
|
||||
var c = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString(colors[i].Hex);
|
||||
dots[i].Background = new System.Windows.Media.SolidColorBrush(c);
|
||||
dots[i].Tag = colors[i].Accent.ToString();
|
||||
}
|
||||
_stripFamily = family;
|
||||
RingAccentStrip();
|
||||
}
|
||||
private Border[] StripDots => [];
|
||||
|
||||
// Ring the strip's selected swatch for the family it is showing.
|
||||
private void RingAccentStrip()
|
||||
{
|
||||
if (AccentStrip is null) return;
|
||||
var ring = (System.Windows.Media.Brush)FindResource("TextBrush");
|
||||
var chosen = _stripFamily switch
|
||||
{
|
||||
Theme.Light => ThemeManager.LightAccentChoice,
|
||||
Theme.Black => ThemeManager.BlackAccentChoice,
|
||||
Theme.SE98 => ThemeManager.SE98AccentChoice,
|
||||
_ => ThemeManager.DarkAccentChoice,
|
||||
};
|
||||
foreach (var dot in StripDots)
|
||||
{
|
||||
bool sel = dot.Tag is string t && Enum.TryParse<DarkAccent>(t, out var a) && a == chosen;
|
||||
dot.BorderBrush = sel ? ring : System.Windows.Media.Brushes.Transparent;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAccentStrip(bool animate)
|
||||
{
|
||||
var cur = ThemeManager.Current;
|
||||
bool show = cur is Theme.Dark or Theme.Light or Theme.Black or Theme.SE98;
|
||||
if (show)
|
||||
{
|
||||
if (animate && _stripOpen && _stripFamily != cur)
|
||||
{
|
||||
// Accented -> accented: the strip stays open and the swatches CROSSFADE.
|
||||
// Re-running the open animation here snapped the strip shut and back.
|
||||
var target = cur;
|
||||
var fadeOut = new System.Windows.Media.Animation.DoubleAnimation(1, 0, TimeSpan.FromMilliseconds(90));
|
||||
fadeOut.Completed += (_, __) =>
|
||||
{
|
||||
PopulateAccentStrip(target);
|
||||
AccentStrip.BeginAnimation(OpacityProperty,
|
||||
new System.Windows.Media.Animation.DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(90)));
|
||||
};
|
||||
AccentStrip.BeginAnimation(OpacityProperty, fadeOut);
|
||||
}
|
||||
else PopulateAccentStrip(cur);
|
||||
}
|
||||
SlideAccentStrip(show, animate);
|
||||
}
|
||||
|
||||
// Width slide, eased - one element animates now, so the old linear lockstep constraint
|
||||
// that kept two rows summing to a constant height no longer applies.
|
||||
private void SlideAccentStrip(bool show, bool animate)
|
||||
{
|
||||
if (show == _stripOpen && animate) return; // already there; crossfade handles content
|
||||
_stripOpen = show;
|
||||
AccentStripHost.BeginAnimation(WidthProperty, null); // drop any in-flight slide
|
||||
if (!animate) { AccentStripHost.Width = show ? AccentStripWidth : 0; return; }
|
||||
double from = double.IsNaN(AccentStripHost.Width) ? AccentStripHost.ActualWidth : AccentStripHost.Width;
|
||||
var anim = new System.Windows.Media.Animation.DoubleAnimation(from, show ? AccentStripWidth : 0,
|
||||
TimeSpan.FromMilliseconds(AccentStripSlideMs))
|
||||
{
|
||||
EasingFunction = new System.Windows.Media.Animation.QuadraticEase
|
||||
{ EasingMode = System.Windows.Media.Animation.EasingMode.EaseOut }
|
||||
};
|
||||
anim.Completed += (_, __) =>
|
||||
{
|
||||
AccentStripHost.BeginAnimation(WidthProperty, null);
|
||||
AccentStripHost.Width = _stripOpen ? AccentStripWidth : 0;
|
||||
};
|
||||
AccentStripHost.BeginAnimation(WidthProperty, anim);
|
||||
}
|
||||
|
||||
// Localized display name for each theme, shown on the picker row.
|
||||
private string ThemeDisplayName(Theme t) => t switch
|
||||
{
|
||||
Theme.Light => Loc("Str_Theme_Light"),
|
||||
Theme.Black => Loc("Str_Theme_Black"),
|
||||
Theme.SE98 => Loc("Str_Theme_98SE"),
|
||||
Theme.Blood => Loc("Str_Theme_Blood"),
|
||||
Theme.Greed => Loc("Str_Theme_Greed"),
|
||||
Theme.Cyanotic => Loc("Str_Theme_Cyanotic"),
|
||||
Theme.Ectoplasm => Loc("Str_Theme_Ectoplasm"),
|
||||
Theme.Decay => Loc("Str_Theme_Decay"),
|
||||
Theme.Mourning => Loc("Str_Theme_Mourning"),
|
||||
Theme.Sepulchre => Loc("Str_Theme_Sepulchre"),
|
||||
Theme.Delirium => Loc("Str_Theme_Delirium"),
|
||||
Theme.Malaise => Loc("Str_Theme_Malaise"),
|
||||
_ => Loc("Str_Theme_Dark"),
|
||||
};
|
||||
|
||||
@@ -518,7 +341,7 @@ namespace KillerPDF
|
||||
// DynamicResource strings. Called once from the window ctor; the event only ever fires
|
||||
// when the app was started with --lang-file.
|
||||
internal void HookExternalLangReload()
|
||||
=> KillerPDF.Services.LocaleManager.ExternalReloaded += () =>
|
||||
=> MmdPdf.Services.LocaleManager.ExternalReloaded += () =>
|
||||
{
|
||||
ApplyToolNumberTooltips();
|
||||
BuildToolbarMenu();
|
||||
@@ -527,22 +350,22 @@ namespace KillerPDF
|
||||
RefreshOpenAnnotationBars();
|
||||
};
|
||||
|
||||
private void LangEnRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.EnUS);
|
||||
private void LangCsRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.CsCZ);
|
||||
private void LangEsRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.Es);
|
||||
private void LangFrRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.Fr);
|
||||
private void LangZhTWRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.ZhTW);
|
||||
private void LangZhCNRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.ZhCN);
|
||||
private void LangBnRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.Bn);
|
||||
private void LangTrRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.TrTR);
|
||||
private void LangDeRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.De);
|
||||
private void LangJaRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.JaJP);
|
||||
private void LangPlRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.PlPL);
|
||||
private void LangHuRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(KillerPDF.Services.Locale.HuHU);
|
||||
private void LangEnRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.EnUS);
|
||||
private void LangCsRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.CsCZ);
|
||||
private void LangEsRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.Es);
|
||||
private void LangFrRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.Fr);
|
||||
private void LangZhTWRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.ZhTW);
|
||||
private void LangZhCNRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.ZhCN);
|
||||
private void LangBnRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.Bn);
|
||||
private void LangTrRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.TrTR);
|
||||
private void LangDeRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.De);
|
||||
private void LangJaRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.JaJP);
|
||||
private void LangPlRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.PlPL);
|
||||
private void LangHuRadio_Checked(object sender, RoutedEventArgs e) => SelectLocale(MmdPdf.Services.Locale.HuHU);
|
||||
|
||||
private void SelectLocale(KillerPDF.Services.Locale loc)
|
||||
private void SelectLocale(MmdPdf.Services.Locale loc)
|
||||
{
|
||||
KillerPDF.Services.LocaleManager.Apply(loc);
|
||||
MmdPdf.Services.LocaleManager.Apply(loc);
|
||||
ApplyToolNumberTooltips(); // re-append the numbers to the now-localized tool tooltips
|
||||
BuildToolbarMenu(); // the toolbar right-click picker's items carry Loc() captions
|
||||
LangFlyout.IsOpen = false; // a pick closes the rail flyout, like the accordion used to collapse
|
||||
@@ -592,9 +415,9 @@ namespace KillerPDF
|
||||
RefreshOpenAnnotationBars(active);
|
||||
}
|
||||
|
||||
private void RefreshOpenAnnotationBars(KillerPDF.Controls.PdfViewer viewer)
|
||||
private void RefreshOpenAnnotationBars(MmdPdf.Controls.PdfViewer viewer)
|
||||
{
|
||||
((KillerPDF.Features.IViewerHost)this).RunWithViewerContext(viewer, () =>
|
||||
((MmdPdf.Features.IViewerHost)this).RunWithViewerContext(viewer, () =>
|
||||
{
|
||||
var tool = _annotBarTool;
|
||||
if (tool == EditTool.Text)
|
||||
@@ -638,17 +461,17 @@ namespace KillerPDF
|
||||
}
|
||||
|
||||
// Native name (autonym) for each language, shown in the picker regardless of UI locale.
|
||||
private static string LangDisplayName(KillerPDF.Services.Locale loc) => loc switch
|
||||
private static string LangDisplayName(MmdPdf.Services.Locale loc) => loc switch
|
||||
{
|
||||
KillerPDF.Services.Locale.CsCZ => "Čeština",
|
||||
KillerPDF.Services.Locale.Es => "Español",
|
||||
KillerPDF.Services.Locale.Fr => "Français",
|
||||
KillerPDF.Services.Locale.ZhTW => "中文 (繁體)",
|
||||
KillerPDF.Services.Locale.ZhCN => "中文 (简体)",
|
||||
KillerPDF.Services.Locale.Bn => "বাংলা",
|
||||
KillerPDF.Services.Locale.TrTR => "Türkçe",
|
||||
KillerPDF.Services.Locale.De => "Deutsch",
|
||||
KillerPDF.Services.Locale.JaJP => "日本語",
|
||||
MmdPdf.Services.Locale.CsCZ => "Čeština",
|
||||
MmdPdf.Services.Locale.Es => "Español",
|
||||
MmdPdf.Services.Locale.Fr => "Français",
|
||||
MmdPdf.Services.Locale.ZhTW => "中文 (繁體)",
|
||||
MmdPdf.Services.Locale.ZhCN => "中文 (简体)",
|
||||
MmdPdf.Services.Locale.Bn => "বাংলা",
|
||||
MmdPdf.Services.Locale.TrTR => "Türkçe",
|
||||
MmdPdf.Services.Locale.De => "Deutsch",
|
||||
MmdPdf.Services.Locale.JaJP => "日本語",
|
||||
_ => "English",
|
||||
};
|
||||
|
||||
@@ -670,7 +493,7 @@ namespace KillerPDF
|
||||
// ── Toolbar appearance (right-click picker on the bar) ────────────
|
||||
// Hover tooltips stay on in every mode, so the text modes are about preference, not
|
||||
// discoverability.
|
||||
// TWO AXES, NOT ONE (family standard, 2026-07-30; KillerUI/Shell/ToolbarStyle.cs is
|
||||
// TWO AXES, NOT ONE (family standard, 2026-07-30; MmdPdfUI/Shell/ToolbarStyle.cs is
|
||||
// the reference). The old five-way ToolbarStyle could not express "large icons WITH text" -
|
||||
// icon size and text placement were never one axis, they only looked like one. The old
|
||||
// enum survives solely so an existing install's saved setting migrates (InitToolbarStyle).
|
||||
@@ -1192,5 +1015,34 @@ namespace KillerPDF
|
||||
{
|
||||
OverflowChevron.IsChecked = false; // close the flyout after a choice is made
|
||||
}
|
||||
|
||||
private void SyncPickerState()
|
||||
{
|
||||
var cur = ThemeManager.Current;
|
||||
// Sync language picker
|
||||
var curLoc = MmdPdf.Services.LocaleManager.Current;
|
||||
LangEnRadio.IsChecked = curLoc == MmdPdf.Services.Locale.EnUS;
|
||||
LangCsRadio.IsChecked = curLoc == MmdPdf.Services.Locale.CsCZ;
|
||||
LangEsRadio.IsChecked = curLoc == MmdPdf.Services.Locale.Es;
|
||||
LangFrRadio.IsChecked = curLoc == MmdPdf.Services.Locale.Fr;
|
||||
LangZhTWRadio.IsChecked = curLoc == MmdPdf.Services.Locale.ZhTW;
|
||||
LangZhCNRadio.IsChecked = curLoc == MmdPdf.Services.Locale.ZhCN;
|
||||
LangBnRadio.IsChecked = curLoc == MmdPdf.Services.Locale.Bn;
|
||||
LangTrRadio.IsChecked = curLoc == MmdPdf.Services.Locale.TrTR;
|
||||
LangDeRadio.IsChecked = curLoc == MmdPdf.Services.Locale.De;
|
||||
LangJaRadio.IsChecked = curLoc == MmdPdf.Services.Locale.JaJP;
|
||||
LangPlRadio.IsChecked = curLoc == MmdPdf.Services.Locale.PlPL;
|
||||
LangHuRadio.IsChecked = curLoc == MmdPdf.Services.Locale.HuHU;
|
||||
// Sync view mode radios. Against the PENDING mode while a fade-wrapped switch is in
|
||||
// flight (_viewMode lags until the fade-out lands), so wheel-cycling with the flyout
|
||||
// open moves the checkmark in step instead of one notch behind.
|
||||
var vm = _pendingViewMode ?? _viewMode;
|
||||
ViewSingleRadio.IsChecked = vm == ViewMode.Single;
|
||||
ViewContinuousRadio.IsChecked = vm == ViewMode.Continuous;
|
||||
ViewTwoPageRadio.IsChecked = vm == ViewMode.TwoPage;
|
||||
ViewGridRadio.IsChecked = vm == ViewMode.Grid;
|
||||
// (The toolbar picker lives on the toolbar's own right-click menu, and the sidebar
|
||||
// side on the sidebar's - both build their checks fresh on open, nothing to sync here.)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
// ============================================================
|
||||
// Keyboard-shortcuts overlay: the LIST view.
|
||||
|
||||
+108
-108
@@ -4,7 +4,7 @@ using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
// Configurable sidebar placement (left or right). The layout uses three columns in
|
||||
// MainContentGrid: one sized sidebar column, a 6px splitter, and a star document column.
|
||||
@@ -12,113 +12,6 @@ namespace KillerPDF
|
||||
// existing collapse / resize logic keeps working unchanged.
|
||||
public partial class MainWindow
|
||||
{
|
||||
private void ApplySidebarSide()
|
||||
{
|
||||
// SplitHost, NOT Viewer. Since the split landed, the element that sits in
|
||||
// MainContentGrid is the SPLIT HOST - Viewer is one of its children. Setting
|
||||
// Grid.Column on Viewer therefore moved pane A into SplitHost's column 2, which is
|
||||
// PaneBCol and is ZERO WIDTH while unsplit, so the document rendered into a pane with
|
||||
// no width and the whole content area went blank. Same for the margin below: the 8px
|
||||
// gutter to the window edge belongs to the host, not to one pane.
|
||||
//
|
||||
// Do NOT look up TabStripBorder / TabScroll here: those elements live inside PdfViewer,
|
||||
// so FindName cannot see them (a UserControl is its own namescope and FindName returns
|
||||
// null SILENTLY). They would only re-span the band across the splitter column, which is
|
||||
// meaningless when each strip lives inside its own pane and spans it exactly.
|
||||
if (FindName("SidebarCol") is not ColumnDefinition sidebarColDef ||
|
||||
FindName("DocCol") is not ColumnDefinition docColDef ||
|
||||
FindName("SidebarOuterGrid") is not Grid sbOuter ||
|
||||
FindName("SidebarBorder") is not Border sbContent ||
|
||||
FindName("SidebarToggleStrip") is not Border sbToggle ||
|
||||
SplitHost is not FrameworkElement docPane ||
|
||||
FindName("SbContentCol") is not ColumnDefinition sbContentCol ||
|
||||
FindName("SbToggleCol") is not ColumnDefinition sbToggleCol)
|
||||
return;
|
||||
|
||||
// Carry the sized column's current width across a flip (24px when collapsed, else the
|
||||
// user's width). A star length means it isn't the sized column yet, so fall back.
|
||||
GridLength sized = _sidebarCollapsed
|
||||
? new GridLength(SbPx(24))
|
||||
: (_sidebarCol != null && _sidebarCol.Width.GridUnitType == GridUnitType.Pixel)
|
||||
? _sidebarCol.Width
|
||||
: new GridLength(SbPx(180));
|
||||
double maxW = SbPx(_sidebarShowingOutlines ? SidebarMaxOutlines : SidebarMaxPages);
|
||||
|
||||
if (!_sidebarRight)
|
||||
{
|
||||
// Sidebar on the LEFT (column 0); document fills column 2.
|
||||
sidebarColDef.MinWidth = SbPx(_sidebarCollapsed ? 24 : SidebarMinOpen); sidebarColDef.MaxWidth = maxW; sidebarColDef.Width = sized;
|
||||
docColDef.MinWidth = 0; docColDef.MaxWidth = double.PositiveInfinity;
|
||||
docColDef.Width = new GridLength(1, GridUnitType.Star);
|
||||
Grid.SetColumn(sbOuter, 0);
|
||||
Grid.SetColumn(docPane, 2);
|
||||
_sidebarCol = sidebarColDef;
|
||||
// Toggle strip faces the document: right edge of the sidebar.
|
||||
sbContentCol.Width = new GridLength(1, GridUnitType.Star);
|
||||
sbToggleCol.Width = new GridLength(24, GridUnitType.Pixel);
|
||||
Grid.SetColumn(sbContent, 0);
|
||||
Grid.SetColumn(sbToggle, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sidebar on the RIGHT (column 2); document fills column 0.
|
||||
docColDef.MinWidth = SbPx(_sidebarCollapsed ? 24 : SidebarMinOpen); docColDef.MaxWidth = maxW; docColDef.Width = sized;
|
||||
sidebarColDef.MinWidth = 0; sidebarColDef.MaxWidth = double.PositiveInfinity;
|
||||
sidebarColDef.Width = new GridLength(1, GridUnitType.Star);
|
||||
Grid.SetColumn(sbOuter, 2);
|
||||
Grid.SetColumn(docPane, 0);
|
||||
_sidebarCol = docColDef;
|
||||
// Toggle strip faces the document: left edge of the sidebar (inner column 0). The
|
||||
// inner column defs are fixed in position, so size them by position, not by name.
|
||||
sbContentCol.Width = new GridLength(24, GridUnitType.Pixel); // inner col 0 -> toggle
|
||||
sbToggleCol.Width = new GridLength(1, GridUnitType.Star); // inner col 1 -> content
|
||||
Grid.SetColumn(sbToggle, 0);
|
||||
Grid.SetColumn(sbContent, 1);
|
||||
}
|
||||
|
||||
// The splitter's edge-line and the SidebarShadow gradient were both handled here. The
|
||||
// splitter draws a single centered line now, which is symmetric and so needs no side
|
||||
// handling, and the fake elevation gradient is gone - DocPaneBorder casts a real
|
||||
// PaneShadow on all four sides. (2026-07-31.)
|
||||
|
||||
// The DocTopAccent / DocBottomAccent repositioning was here. Those two 1px rules are
|
||||
// gone with the squared layout - the card carries its own border on all four sides now,
|
||||
// so there is nothing left to bridge to the toolbar and footer. (2026-07-31.)
|
||||
|
||||
// The document card's 8px inset always sits on its OUTER edge - the window side, away
|
||||
// from the splitter - so the gap reads as a margin off the window rather than a gutter
|
||||
// between the pane and the sidebar. Full screen clears the margin, so leave it alone
|
||||
// there; ApplyFullScreen restores it from this same helper on exit.
|
||||
// The grip rides the CONTENT column and faces the rail, so it always sits on the list's
|
||||
// inner lip: right edge with the sidebar on the left, left edge with it on the right.
|
||||
if (FindName("SidebarSplitter") is Thumb grip)
|
||||
{
|
||||
Grid.SetColumn(grip, _sidebarRight ? 1 : 0);
|
||||
grip.HorizontalAlignment = _sidebarRight ? HorizontalAlignment.Left
|
||||
: HorizontalAlignment.Right;
|
||||
}
|
||||
|
||||
// The shadow caster is inside the PdfViewer control, so moving the control moves both -
|
||||
// one less thing that can drift out of alignment than a separate grid child that has to
|
||||
// be moved in step with the pane.
|
||||
if (!_fullScreen)
|
||||
{
|
||||
// docPane is SplitHost, so this one margin now insets BOTH panes from the window
|
||||
// edge together, which is what the 8px gutter always meant.
|
||||
docPane.Margin = DocPaneInsetMargin();
|
||||
// No tab-band or TabBarRing margins here. Those exist only to stop a window-level
|
||||
// band overhanging the card's rounded outer corner, where the band runs the full
|
||||
// width while the card is inset 8px. Each strip is inside its own pane and spans
|
||||
// exactly that pane, so the band and the card share an edge by construction.
|
||||
}
|
||||
|
||||
UpdateSidebarToggleGlyph();
|
||||
SyncThemeFlyoutSide();
|
||||
UpdateTabStripFade();
|
||||
// The column swap repositions the document pane; re-anchor the footer shadow once layout
|
||||
// settles (TransformToVisual needs the final positions).
|
||||
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Loaded, (Action)UpdateFooterFade);
|
||||
}
|
||||
|
||||
// Document on the right (sidebar left) -> 8px inset on the right; mirrored when the sidebar
|
||||
// moves. Top and bottom stay 0: PaneShadow is Direction 270 and draws outside the element's
|
||||
@@ -339,5 +232,112 @@ namespace KillerPDF
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ApplySidebarSide()
|
||||
{
|
||||
// SplitHost, NOT Viewer. Since the split landed, the element that sits in
|
||||
// MainContentGrid is the SPLIT HOST - Viewer is one of its children. Setting
|
||||
// Grid.Column on Viewer therefore moved pane A into SplitHost's column 2, which is
|
||||
// PaneBCol and is ZERO WIDTH while unsplit, so the document rendered into a pane with
|
||||
// no width and the whole content area went blank. Same for the margin below: the 8px
|
||||
// gutter to the window edge belongs to the host, not to one pane.
|
||||
//
|
||||
// Do NOT look up TabStripBorder / TabScroll here: those elements live inside PdfViewer,
|
||||
// so FindName cannot see them (a UserControl is its own namescope and FindName returns
|
||||
// null SILENTLY). They would only re-span the band across the splitter column, which is
|
||||
// meaningless when each strip lives inside its own pane and spans it exactly.
|
||||
if (FindName("SidebarCol") is not ColumnDefinition sidebarColDef ||
|
||||
FindName("DocCol") is not ColumnDefinition docColDef ||
|
||||
FindName("SidebarOuterGrid") is not Grid sbOuter ||
|
||||
FindName("SidebarBorder") is not Border sbContent ||
|
||||
FindName("SidebarToggleStrip") is not Border sbToggle ||
|
||||
SplitHost is not FrameworkElement docPane ||
|
||||
FindName("SbContentCol") is not ColumnDefinition sbContentCol ||
|
||||
FindName("SbToggleCol") is not ColumnDefinition sbToggleCol)
|
||||
return;
|
||||
|
||||
// Carry the sized column's current width across a flip (24px when collapsed, else the
|
||||
// user's width). A star length means it isn't the sized column yet, so fall back.
|
||||
GridLength sized = _sidebarCollapsed
|
||||
? new GridLength(SbPx(24))
|
||||
: (_sidebarCol != null && _sidebarCol.Width.GridUnitType == GridUnitType.Pixel)
|
||||
? _sidebarCol.Width
|
||||
: new GridLength(SbPx(180));
|
||||
double maxW = SbPx(_sidebarShowingOutlines ? SidebarMaxOutlines : SidebarMaxPages);
|
||||
|
||||
if (!_sidebarRight)
|
||||
{
|
||||
// Sidebar on the LEFT (column 0); document fills column 2.
|
||||
sidebarColDef.MinWidth = SbPx(_sidebarCollapsed ? 24 : SidebarMinOpen); sidebarColDef.MaxWidth = maxW; sidebarColDef.Width = sized;
|
||||
docColDef.MinWidth = 0; docColDef.MaxWidth = double.PositiveInfinity;
|
||||
docColDef.Width = new GridLength(1, GridUnitType.Star);
|
||||
Grid.SetColumn(sbOuter, 0);
|
||||
Grid.SetColumn(docPane, 2);
|
||||
_sidebarCol = sidebarColDef;
|
||||
// Toggle strip faces the document: right edge of the sidebar.
|
||||
sbContentCol.Width = new GridLength(1, GridUnitType.Star);
|
||||
sbToggleCol.Width = new GridLength(24, GridUnitType.Pixel);
|
||||
Grid.SetColumn(sbContent, 0);
|
||||
Grid.SetColumn(sbToggle, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sidebar on the RIGHT (column 2); document fills column 0.
|
||||
docColDef.MinWidth = SbPx(_sidebarCollapsed ? 24 : SidebarMinOpen); docColDef.MaxWidth = maxW; docColDef.Width = sized;
|
||||
sidebarColDef.MinWidth = 0; sidebarColDef.MaxWidth = double.PositiveInfinity;
|
||||
sidebarColDef.Width = new GridLength(1, GridUnitType.Star);
|
||||
Grid.SetColumn(sbOuter, 2);
|
||||
Grid.SetColumn(docPane, 0);
|
||||
_sidebarCol = docColDef;
|
||||
// Toggle strip faces the document: left edge of the sidebar (inner column 0). The
|
||||
// inner column defs are fixed in position, so size them by position, not by name.
|
||||
sbContentCol.Width = new GridLength(24, GridUnitType.Pixel); // inner col 0 -> toggle
|
||||
sbToggleCol.Width = new GridLength(1, GridUnitType.Star); // inner col 1 -> content
|
||||
Grid.SetColumn(sbToggle, 0);
|
||||
Grid.SetColumn(sbContent, 1);
|
||||
}
|
||||
|
||||
// The splitter's edge-line and the SidebarShadow gradient were both handled here. The
|
||||
// splitter draws a single centered line now, which is symmetric and so needs no side
|
||||
// handling, and the fake elevation gradient is gone - DocPaneBorder casts a real
|
||||
// PaneShadow on all four sides. (2026-07-31.)
|
||||
|
||||
// The DocTopAccent / DocBottomAccent repositioning was here. Those two 1px rules are
|
||||
// gone with the squared layout - the card carries its own border on all four sides now,
|
||||
// so there is nothing left to bridge to the toolbar and footer. (2026-07-31.)
|
||||
|
||||
// The document card's 8px inset always sits on its OUTER edge - the window side, away
|
||||
// from the splitter - so the gap reads as a margin off the window rather than a gutter
|
||||
// between the pane and the sidebar. Full screen clears the margin, so leave it alone
|
||||
// there; ApplyFullScreen restores it from this same helper on exit.
|
||||
// The grip rides the CONTENT column and faces the rail, so it always sits on the list's
|
||||
// inner lip: right edge with the sidebar on the left, left edge with it on the right.
|
||||
if (FindName("SidebarSplitter") is Thumb grip)
|
||||
{
|
||||
Grid.SetColumn(grip, _sidebarRight ? 1 : 0);
|
||||
grip.HorizontalAlignment = _sidebarRight ? HorizontalAlignment.Left
|
||||
: HorizontalAlignment.Right;
|
||||
}
|
||||
|
||||
// The shadow caster is inside the PdfViewer control, so moving the control moves both -
|
||||
// one less thing that can drift out of alignment than a separate grid child that has to
|
||||
// be moved in step with the pane.
|
||||
if (!_fullScreen)
|
||||
{
|
||||
// docPane is SplitHost, so this one margin now insets BOTH panes from the window
|
||||
// edge together, which is what the 8px gutter always meant.
|
||||
docPane.Margin = DocPaneInsetMargin();
|
||||
// No tab-band or TabBarRing margins here. Those exist only to stop a window-level
|
||||
// band overhanging the card's rounded outer corner, where the band runs the full
|
||||
// width while the card is inset 8px. Each strip is inside its own pane and spans
|
||||
// exactly that pane, so the band and the card share an edge by construction.
|
||||
}
|
||||
|
||||
UpdateSidebarToggleGlyph();
|
||||
UpdateTabStripFade();
|
||||
// The column swap repositions the document pane; re-anchor the footer shadow once layout
|
||||
// settles (TransformToVisual needs the final positions).
|
||||
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Loaded, (Action)UpdateFooterFade);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -657,7 +657,7 @@ namespace KillerPDF
|
||||
}
|
||||
|
||||
// CountOutlines, RemoveOutlineRecursive and the stale-link-key scrubs live in
|
||||
// Services/PdfOutlines.cs (KillerUI refactor) - pure functions over the outline tree.
|
||||
// Services/PdfOutlines.cs (MmdPdfUI refactor) - pure functions over the outline tree.
|
||||
|
||||
/// <summary>Rebuilds the outline panel after an edit, keeping every branch's expand/collapse
|
||||
/// state (the PdfOutline objects survive the rebuild, so they key the state).</summary>
|
||||
|
||||
+5
-5
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -789,7 +789,7 @@ namespace KillerPDF
|
||||
{
|
||||
if (strokes.Count == 0)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Dlg_DrawSignatureFirst"), "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
KillerDialog.Show(this, Loc("Str_Dlg_DrawSignatureFirst"), "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -829,7 +829,7 @@ namespace KillerPDF
|
||||
btnPanel.Margin = new Thickness(12, 4, 12, 12);
|
||||
contentArea.Children.Add(btnPanel);
|
||||
|
||||
win.Content = DialogChrome.Frame(win, this, "KillerPDF - " + Loc("Str_Sig_Create"), () => win.Close(), contentArea);
|
||||
win.Content = DialogChrome.Frame(win, this, "MmdPdf - " + Loc("Str_Sig_Create"), () => win.Close(), contentArea);
|
||||
win.ShowDialog();
|
||||
}
|
||||
|
||||
@@ -872,7 +872,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_ImportImageFailed") + "\n" + ex.Message, "KillerPDF",
|
||||
KillerDialog.Show(this, Loc("Str_Err_ImportImageFailed") + "\n" + ex.Message, "MmdPdf",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,9 +3,9 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using KillerPDF.Controls;
|
||||
using MmdPdf.Controls;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
/// <summary>
|
||||
/// Two document panes side by side in one window.
|
||||
|
||||
+2
-2
@@ -5,9 +5,9 @@ using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using PdfSharpCore.Drawing;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
|
||||
+5
-5
@@ -6,7 +6,7 @@ using System.Windows.Interop;
|
||||
using System.Windows.Media.Animation;
|
||||
|
||||
// ============================================================
|
||||
// THEMED WINDOWS SYSTEM MENU (from KillerUI/Shell/SystemMenu.cs)
|
||||
// THEMED WINDOWS SYSTEM MENU (from MmdPdfUI/Shell/SystemMenu.cs)
|
||||
//
|
||||
// WindowChrome turns the title bar into a real native caption, which is what buys free snap,
|
||||
// drag and double-click-maximize - but it also means Windows answers a caption right-click
|
||||
@@ -19,11 +19,11 @@ using System.Windows.Media.Animation;
|
||||
// WM_SYSCOMMAND the native menu would have sent, so behavior is identical - including Move and
|
||||
// Size, which hand off to Windows' own modal drag loops.
|
||||
//
|
||||
// KillerPDF adaptations: HTCAPTION already lives in Shell/WindowChrome.cs (not redeclared
|
||||
// MmdPdf adaptations: HTCAPTION already lives in Shell/WindowChrome.cs (not redeclared
|
||||
// here), the menu comes from MakeThemedMenu() so its TextOptions match the app's other
|
||||
// code-built menus, and the kit's Anim.FadeIn is inlined (KillerPDF carries no Anim class).
|
||||
// code-built menus, and the kit's Anim.FadeIn is inlined (MmdPdf carries no Anim class).
|
||||
// ============================================================
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -90,7 +90,7 @@ namespace KillerPDF
|
||||
};
|
||||
}
|
||||
|
||||
// KillerPDF keeps its implicit ContextMenu/MenuItem styles in MainWindow.xaml's
|
||||
// MmdPdf keeps its implicit ContextMenu/MenuItem styles in MainWindow.xaml's
|
||||
// WINDOW resources (not App.xaml), and an Absolute-placement menu has no inheritance
|
||||
// context to find them through - it rendered stock white. PlacementTarget supplies
|
||||
// that context; with PlacementMode.Absolute it does not affect position.
|
||||
|
||||
+2
-2
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
|
||||
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -680,7 +680,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_LoadImageFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_LoadImageFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,7 +764,7 @@ namespace KillerPDF
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
KillerDialog.Show(this, Loc("Str_Err_PasteFailed") + "\n" + ex.Message, "KillerPDF", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
KillerDialog.Show(this, Loc("Str_Err_PasteFailed") + "\n" + ex.Message, "MmdPdf", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
|
||||
@@ -16,10 +16,10 @@ using Microsoft.Win32;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
using KillerPDF.Services;
|
||||
using MmdPdf.Services;
|
||||
using PdfPigDoc = UglyToad.PdfPig.PdfDocument;
|
||||
|
||||
namespace KillerPDF
|
||||
namespace MmdPdf
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
@@ -289,7 +289,7 @@ namespace KillerPDF
|
||||
bool updating = machineInstallExists || userInstallExists;
|
||||
// Two checkboxes, matching Killendar and KillerShell: the desktop shortcut (on by
|
||||
// default, as it always was) and the all-users install. If an all-users copy already
|
||||
// exists, keep that scope selected: KillerPDF deliberately supports one installed
|
||||
// exists, keep that scope selected: MmdPdf deliberately supports one installed
|
||||
// copy, not competing Program Files and per-user installations.
|
||||
var (confirmed, wantDesktop, allUsers) = KillerDialog.ShowTwoCheckPrompt(this,
|
||||
Loc(machineInstallExists ? "Str_Dlg_UpdateMachineMsg" :
|
||||
|
||||
Reference in New Issue
Block a user