19 Commits

Author SHA1 Message Date
mbabienco df11b65c05 Fix focusing and clipboard use 2026-04-08 12:54:35 +09:00
mbabienco fc963d88f7 Fix deprecations regarding Watermark 2026-04-08 12:54:28 +09:00
mbabienco 600ae58f25 Use OpenGL rendering 2026-04-08 12:54:18 +09:00
mbabienco 0783e0b544 Update packages to Avalonia 12 compatible 2026-04-08 12:54:11 +09:00
mbabienco d90cd1354f Bump version 2026-03-13 08:18:32 +09:00
mbabienco f4dd498d22 Shortcut to view settings dir 2026-03-13 08:14:50 +09:00
mbabienco cd71df8a8e Add yyyy.MM.dd to acceptable formats 2026-03-13 08:10:11 +09:00
mbabienco de621fe9dc Add another file name date parsing format
Also redid code so more formats would be easy
2026-03-13 08:05:11 +09:00
mbabienco a1858443e8 Bump version number 2026-03-12 21:17:27 +09:00
mbabienco f34a7092e4 Resize PDF images too (Docnet rendering) 2026-03-12 21:09:34 +09:00
mbabienco aed85c7555 Use page size and pg items to calc max image size 2026-03-12 20:58:20 +09:00
mbabienco 25f739667d Allow resolving Noto Sans font 2026-03-12 20:56:38 +09:00
mbabienco 1fae3f5341 Redo image resizing
Hack fix guesswork sizing
2026-03-12 20:21:41 +09:00
mbabienco 5dda88521d Add black border around images/pdfs
Makes viewing things with no border/white border much easier.
2026-03-12 19:34:56 +09:00
mbabienco 742ecb148a Simply if statement 2026-03-12 19:07:25 +09:00
mbabienco 4ad4a0852f Bump Magick.NET for vulnerability 2026-03-12 19:02:17 +09:00
mbabienco c44093c5ee Fix wrong About menu title 2026-03-04 21:10:21 +09:00
mbabienco 71f4fda2d4 Remove unneeded TODO comment 2026-03-03 12:54:53 +09:00
mbabienco 478f67aa82 Convert remaining files to file-scoped namespace 2026-03-03 12:54:27 +09:00
23 changed files with 410 additions and 229 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
; Non-commercial use only
#define MyAppName "MayShow"
#define MyAppVersion "1.4.0"
#define MyAppVersion "1.4.2"
#define MyAppPublisher "Quickity Quack Productions"
#define MyAppExeName "MayShow.exe"
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/bash
VERSION="1.4.0"
VERSION="1.4.2"
SRC_DIR="src" # user ran script from main folder
if [ ! -d "$SRC_DIR" ]; then
SRC_DIR= "../src" # try
+1 -1
View File
@@ -131,7 +131,7 @@
</Application.Resources>
<NativeMenu.Menu>
<NativeMenu>
<NativeMenuItem Header="About ReceiptBuilder" Click="AboutOnClick" />
<NativeMenuItem Header="About MayShow" Click="AboutOnClick" />
</NativeMenu>
</NativeMenu.Menu>
</Application>
+1 -1
View File
@@ -1,5 +1,5 @@
<Project>
<PropertyGroup>
<AvaloniaVersion>11.3.12</AvaloniaVersion>
<AvaloniaVersion>12.0.0</AvaloniaVersion>
</PropertyGroup>
</Project>
+4 -6
View File
@@ -4,16 +4,14 @@ using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
namespace MayShow.Helpers
{
namespace MayShow.Helpers;
// https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifypropertychanged?view=netframework-4.7.2
class ChangeNotifier : INotifyPropertyChanged
{
// https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifypropertychanged?view=netframework-4.7.2
class ChangeNotifier : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ namespace MayShow.Helpers;
class Constants
{
public static string AppVersion = "1.4.0";
public static string AppVersion = "1.4.2";
public static string[] AllowedFileExtensionPatterns = [ "*.png", "*.jpg", "*.jpeg", "*.gif", "*.bmp", "*.webp", "*.pdf", "*.heic", ];
public static string[] AllowedFileExtensionsNoStar = [ "png", "jpg", "jpeg", "gif", "bmp", "webp", "pdf", "heic", ];
+19 -6
View File
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using Tmds.DBus.Protocol;
namespace MayShows.Helpers;
@@ -23,16 +25,27 @@ class Utilities
public static DateOnly? CheckValidDateInString(string str)
{
// https://stackoverflow.com/a/14918404/3938401
var rgx = new Regex(@"\d{4}-\d{2}-\d{2}");
// formats = regex format -> DateTime parsing format
var formats = new Dictionary<string, string>
{
{@"\d{4}-\d{2}-\d{2}", "yyyy-MM-dd"},
{@"\d{4}.d{2}.d{2}", "yyyy.MM.dd"},
{@"\d{8}", "yyyyMMdd"}
};
foreach (var data in formats)
{
var rgx = new Regex(data.Key);
var mat = rgx.Match(str);
if (mat.Success)
{
var dtStr = mat.ToString();
string[] formats = ["yyyy-MM-dd"];
DateTime parsedDateTime;
var didWork = DateTime.TryParseExact(dtStr, formats, CultureInfo.InvariantCulture,
DateTimeStyles.None, out parsedDateTime);
return didWork ? DateOnly.FromDateTime(parsedDateTime) : null;
var didWork = DateTime.TryParseExact(dtStr, [data.Value], CultureInfo.InvariantCulture,
DateTimeStyles.None, out var parsedDateTime);
if (didWork)
{
return DateOnly.FromDateTime(parsedDateTime);
}
}
}
return null;
}
+7 -7
View File
@@ -12,7 +12,7 @@
<PublishTrimmed>true</PublishTrimmed>
<PublishAot>true</PublishAot>
<AssemblyName>MayShow</AssemblyName>
<AssemblyVersion>1.4.0</AssemblyVersion> <!-- Also update Constants version -->
<AssemblyVersion>1.4.2</AssemblyVersion> <!-- Also update Constants version -->
<ApplicationIcon>MayShow-icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
@@ -53,15 +53,15 @@
<PackageReference Include="Avalonia.Themes.Fluent" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)">
<!-- <PackageReference Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
</PackageReference> -->
<PackageReference Include="PDFsharp-MigraDoc" Version="6.2.4" />
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="14.10.3" />
<PackageReference Include="Deadpikle.AvaloniaProgressRing" Version="0.10.11-preview20251127001" />
<PackageReference Include="DialogHost.Avalonia" Version="0.10.4" />
<PackageReference Include="Xaml.Behaviors.Interactions.DragAndDrop.DataGrid" Version="11.3.9.5" />
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="14.11.1" />
<PackageReference Include="Deadpikle.AvaloniaProgressRing" Version="0.11.0" />
<PackageReference Include="DialogHost.Avalonia" Version="0.11.1" />
<PackageReference Include="Xaml.Behaviors.Interactions.DragAndDrop.DataGrid" Version="12.0.0-rc1" />
<PackageReference Include="Docnet.Core" Version="2.6.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
</ItemGroup>
+12 -1
View File
@@ -17,5 +17,16 @@ class Program
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
.LogToTrace()
.With(new AvaloniaNativePlatformOptions
{
// https://github.com/AvaloniaUI/Avalonia/issues/20971
RenderingMode =
[
// put OpenGL first, to have higher priority over Metal
AvaloniaNativeRenderingMode.OpenGl,
AvaloniaNativeRenderingMode.Metal,
AvaloniaNativeRenderingMode.Software
]
});
}
+3 -4
View File
@@ -5,10 +5,10 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace MayShow.ViewModels
namespace MayShow.ViewModels;
class BaseViewModel : ChangeNotifier
{
class BaseViewModel : ChangeNotifier
{
IChangeViewModel _viewModelChanger;
ITopLevelGrabber? _topLevelGrabber;
@@ -43,5 +43,4 @@ namespace MayShow.ViewModels
}
#endregion
}
}
+187 -39
View File
@@ -28,6 +28,8 @@ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System.Reflection.Metadata.Ecma335;
using Docnet.Core.Readers;
using MigraDoc.DocumentObjectModel.Visitors;
using Avalonia.Input.Platform;
namespace MayShow.ViewModels;
@@ -576,6 +578,24 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
public byte[]? GetFont(string faceName)
{
LogInfo(string.Format("Loading font {0}", faceName));
if (faceName == "Noto Sans")
{
var path = Path.Combine(_processDir, "Assets/Fonts/Noto_Sans/static/NotoSans-Regular.ttf");
if (!File.Exists(path))
{
path = Path.Combine(_processDir, "../Resources/Assets/Fonts/Noto_Sans/static/NotoSans-Regular.ttf");
}
return File.ReadAllBytes(path);
}
if (faceName == "Noto Sans Bold")
{
var path = Path.Combine(_processDir, "Assets/Fonts/Noto_Sans/static/NotoSans-Bold.ttf");
if (!File.Exists(path))
{
path = Path.Combine(_processDir, "../Resources/Assets/Fonts/Noto_Sans/static/NotoSans-Bold.ttf");
}
return File.ReadAllBytes(path);
}
if (faceName == "Noto Sans JP")
{
var path = Path.Combine(_processDir, "Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-Regular.ttf");
@@ -600,6 +620,14 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
public FontResolverInfo? ResolveTypeface(string familyName, bool bold, bool italic)
{
// LogInfo(string.Format("Resolving font name {0}", familyName));
if (familyName == "Noto Sans")
{
if (bold)
{
return new FontResolverInfo(familyName + " Bold");
}
return new FontResolverInfo(familyName);
}
if (familyName == "Noto Sans JP")
{
if (bold)
@@ -611,11 +639,47 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
return null;
}
private Paragraph GetFooterParagraph()
{
var footerPar = new Paragraph();
footerPar.Format.Alignment = ParagraphAlignment.Center;
footerPar.Format.Font.Size = 10;
footerPar.AddText("--Page ");
footerPar.AddPageField();
footerPar.AddText(" of ");
footerPar.AddNumPagesField();
footerPar.AddText("--");
footerPar.AddLineBreak();
footerPar.AddText("Report generated on " + DateTime.Now.ToString("f"));
footerPar.Tag = "FooterPar";
footerPar.Format.Font.Name = "Noto Sans";
return footerPar;
}
private decimal GetExistingPageItemHeight(PdfDocumentRenderer pdfRenderer, decimal footerParagraphHeight)
{
pdfRenderer.DocumentRenderer.PrepareDocument();
var currPageCount = pdfRenderer.DocumentRenderer.FormattedDocument?.PageCount;
var heightForExistingItemsOnPage = footerParagraphHeight;
if (currPageCount.HasValue)
{
var renderInfo = pdfRenderer.DocumentRenderer.GetRenderInfoFromPage(currPageCount.Value);
if (renderInfo != null)
{
// Console.WriteLine("Got render info for page: {0}", currPageCount);
foreach (var item in renderInfo)
{
heightForExistingItemsOnPage += (decimal)item.LayoutInfo.ContentArea.Height.Inch;
}
}
}
return heightForExistingItemsOnPage;
}
// https://forum.pdfsharp.net/viewtopic.php?f=2&t=1025
private async Task CreatePDF(string folderPath)
{
// TODO: calculate needed width for images based on page width and margins and all that?
// TODO: resize (non-HEIC) images for smaller size...?
// safety checks
var outputDir = _settings.SaveOutputPdfInWorkingDir ? folderPath : _settings.OutputPdfDir;
if (!Directory.Exists(outputDir))
@@ -623,12 +687,26 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
await DialogHost.Show(new WarningViewModel("Output directory not found! Please adjust your application Settings before continuing. Output directory: " + outputDir));
return;
}
// setup globals and consts...
GlobalFontSettings.FontResolver = this;
GlobalFontSettings.FallbackFontResolver = new FailsafeFontResolver();
const decimal pageWidth = 8.5m;
const decimal pageHeight = 11.0m;
const decimal margin = 0.5m;
const int imageResolution = 72;
const int imageInsertMarginPixels = 30; // we calculate max available; use max - this # for max image size
var maxItemPxWidth = ((pageWidth - (2 * margin)) * imageResolution) - imageInsertMarginPixels;
// start making PDF!
IsCreatingPDF = true;
var pdfDoc = new Document();
var outputFileName = ReportTitle + ".pdf";
var folderName = new DirectoryInfo(folderPath).Name;
const int imageWidth = 425;
const int maxImageWidth = 425;
var imageLineFormat = new MigraDoc.DocumentObjectModel.Shapes.LineFormat()
{
Color = Colors.Black,
Width = Unit.FromPoint(2),
};;
if (folderName.Contains('-'))
{
// see if year/month format
@@ -643,33 +721,51 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
LogInfo("Auto-changed output file name to " + outputFileName);
}
}
// setup initial section (for page characteristics)
var section = pdfDoc.AddSection();
section.PageSetup.PageFormat = PageFormat.Letter;
section.PageSetup.PageWidth = "8.5in";
section.PageSetup.PageHeight = "11in";
section.PageSetup.TopMargin = "0.5in";
section.PageSetup.RightMargin = "0.5in";
section.PageSetup.BottomMargin = "0.5in";
section.PageSetup.LeftMargin = "0.5in";
section.PageSetup.PageWidth = pageWidth + "in";
section.PageSetup.PageHeight = pageHeight + "in";
section.PageSetup.TopMargin = margin + "in";
section.PageSetup.RightMargin = margin + "in";
section.PageSetup.BottomMargin = margin + "in";
section.PageSetup.LeftMargin = margin + "in";
// setup footer for page number
var footerPar = new Paragraph();
footerPar.Format.Alignment = ParagraphAlignment.Center;
footerPar.Format.Font.Size = 10;
footerPar.AddText("--Page ");
footerPar.AddPageField();
footerPar.AddText(" of ");
footerPar.AddNumPagesField();
footerPar.AddText("--");
footerPar.AddLineBreak();
footerPar.AddText("Report generated on " + DateTime.Now.ToString("f"));
var footerPar = GetFooterParagraph();
section.Footers.Primary.Add(footerPar);
// add report title
// create a quick PDF doc renderer to measure footer paragraph height
var footerParagraphHeight = 0.4m; // estimate
var footerOnlyPdfDoc = new Document();
var sectionClone = section.Clone();
footerOnlyPdfDoc.Add(sectionClone);
sectionClone.Add(GetFooterParagraph());
var footerPdfRenderer = new PdfDocumentRenderer
{
Document = footerOnlyPdfDoc
};
footerPdfRenderer.DocumentRenderer.PrepareDocument();
var footerRenderInfo = footerPdfRenderer.DocumentRenderer.GetRenderInfoFromPage(1);
if (footerRenderInfo != null)
{
foreach (var item in footerRenderInfo)
{
if (item.DocumentObject.Tag?.ToString() == "FooterPar")
{
Console.WriteLine("Got footer paragraph height!");
footerParagraphHeight = (decimal)item.LayoutInfo.ContentArea.Height.Inch;
break;
}
}
}
// continue setting up document
// First page only: add report title
var reportTitlePar = section.AddParagraph();
reportTitlePar.Format.Alignment = ParagraphAlignment.Center;
reportTitlePar.Format.Font.Size = 16;
reportTitlePar.Format.Font.Bold = true;
reportTitlePar.Format.Font.Name = "Noto Sans JP"; // has english letters in it, too
reportTitlePar.AddText(ReportTitle);
reportTitlePar.Tag = "TitlePar";
// get converted files directory path and create it if necessary
var convertedDir = Path.Combine(Utilities.GetInternalDataPath(), "converted");
if (!Directory.Exists(convertedDir))
@@ -677,8 +773,11 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
Directory.CreateDirectory(convertedDir);
}
//
GlobalFontSettings.FontResolver = this;
GlobalFontSettings.FallbackFontResolver = new FailsafeFontResolver();
var pdfRenderer = new PdfDocumentRenderer
{
Document = pdfDoc,
WorkingDirectory = folderPath
};
var hasAddedData = false;
for (var i = 0; i < ReportFiles.Count; i++)
{
@@ -705,12 +804,14 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
imageTitlePar.Format.Font.Bold = true;
imageTitlePar.Format.Font.Name = "Noto Sans JP"; // has english letters in it, too
imageTitlePar.AddText(string.IsNullOrWhiteSpace(file.Title) ? file.FileName : file.Title);
imageTitlePar.Tag = "ReceiptTitlePar";
var receiptDatePar = section.AddParagraph();
receiptDatePar.Format.Alignment = ParagraphAlignment.Center;
receiptDatePar.Format.Font.Size = 12;
receiptDatePar.Format.Font.Bold = true;
receiptDatePar.Format.Font.Name = "Noto Sans JP"; // has english letters in it, too
receiptDatePar.AddText(file.ReceiptDate.ToString("yyyy-MM-dd"));
receiptDatePar.Tag = "ReceiptDatePar";
if (!string.IsNullOrWhiteSpace(file.Notes))
{
var imageNotesPar = section.AddParagraph();
@@ -719,8 +820,10 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
imageNotesPar.Format.Font.Bold = false;
imageNotesPar.Format.Font.Name = "Noto Sans JP";
imageNotesPar.AddText(file.Notes);
imageNotesPar.Tag = "ReceiptNotesPar";
}
section.AddParagraph(); // add empty line for spacing
var emptyPar = section.AddParagraph(); // add empty line for spacing
emptyPar.Tag = "EmptyParagraph";
// now add the image
var lowerName = fileName.ToLower();
var isPDF = lowerName.EndsWith(".pdf");
@@ -732,6 +835,14 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
var info = new FileInfo(file.FilePath);
uint loadedImageWidth = 0;
uint loadedImageHeight = 0;
// get max pixel height remaining for items on this page
// (For multi-page PDFs, showing page 2 and on will have more height since they have no title,
// but to keep things consistent we will use the same height for all PDF pages.)
// render up to now on this page and get height remaining in inches
var currPageCount = pdfRenderer.DocumentRenderer.FormattedDocument?.PageCount;
var heightForExistingItemsOnPage = GetExistingPageItemHeight(pdfRenderer, footerParagraphHeight);
var remainingHeightInches = pageHeight - (2 * margin) - heightForExistingItemsOnPage;
var remainingHeightPixels = (remainingHeightInches * imageResolution) - imageInsertMarginPixels;
if (!isPDF)
{
using var mImage = new MagickImage(info.FullName);
@@ -777,17 +888,23 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
var paragraph = section.AddParagraph();
paragraph.Format.Alignment = ParagraphAlignment.Center;
var image = paragraph.AddImage(filePath);
image.LockAspectRatio = true;
if (!isPDF && loadedImageHeight > 600)
image.Resolution = imageResolution; // dots per inch
image.Tag = "ReceiptImageTag";
paragraph.Tag = "ReceiptImageParagraphTag";
image.LineFormat = imageLineFormat.Clone();
// resize down until it will fit on the page
while (loadedImageHeight > remainingHeightPixels || loadedImageWidth > maxItemPxWidth)
{
image.Height = 550; // make sure it will fit on one page
// Console.WriteLine("Image height = {0}, width = {1}; decreasing size by 5% to h={2}, w={3}", loadedImageHeight, loadedImageWidth, (uint)Math.Floor(loadedImageHeight * 0.95), (uint)Math.Floor(loadedImageWidth * 0.95));
// keep reducing size by 5% (little by little) until it fits on the page
// ...might skew ever so slightly but should not be noticable...
loadedImageHeight = (uint)Math.Floor(loadedImageHeight * 0.95);
loadedImageWidth = (uint)Math.Floor(loadedImageWidth * 0.95);
}
else
{
image.Width = imageWidth; // can't be too wide now...not sure why...maybe due to margins...
image.Height = loadedImageHeight;
image.Width = loadedImageWidth;
}
}
else
else // isPDF
{
// need to render PDF to images
if (_settings.UseDocnetPDFImageRendering)
@@ -826,9 +943,23 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
pgCount == 1 ? "" : "s"));
var paragraph = section.AddParagraph();
paragraph.Format.Alignment = ParagraphAlignment.Center;
// get image height/width off of disk so we can resize down if needed
var image = paragraph.AddImage(convertedPdfImagePath);
image.Width = imageWidth;
image.LockAspectRatio = true;
image.LineFormat = imageLineFormat.Clone();
using (var firstPdfPageImage = new MagickImage(convertedPdfImagePath))
{
var pdfPageImageWidth = firstPdfPageImage.Width;
var pdfPageImageHeight = firstPdfPageImage.Height;
// resize down until it will fit on the page
while (pdfPageImageHeight > remainingHeightPixels || pdfPageImageWidth > maxItemPxWidth)
{
pdfPageImageHeight = (uint)Math.Floor(pdfPageImageHeight * 0.95);
pdfPageImageWidth = (uint)Math.Floor(pdfPageImageWidth * 0.95);
}
image.Height = pdfPageImageHeight;
image.Width = pdfPageImageWidth;
}
for (var j = 1; j < pgCount; j++)
{
section.AddPageBreak();
@@ -837,18 +968,37 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
convertedPdfImagePath = RenderPdfPageToImage(docReader, j);
image = paragraph.AddImage(convertedPdfImagePath);
image.LockAspectRatio = true;
image.Width = imageWidth;
image.Width = maxImageWidth;
image.LineFormat = imageLineFormat.Clone();
using (var otherPdfPageImage = new MagickImage(convertedPdfImagePath))
{
var pdfPageImageWidth = otherPdfPageImage.Width;
var pdfPageImageHeight = otherPdfPageImage.Height;
// resize down until it will fit on the page
while (pdfPageImageHeight > remainingHeightPixels || pdfPageImageWidth > maxItemPxWidth)
{
pdfPageImageHeight = (uint)Math.Floor(pdfPageImageHeight * 0.95);
pdfPageImageWidth = (uint)Math.Floor(pdfPageImageWidth * 0.95);
}
image.Height = pdfPageImageHeight;
image.Width = pdfPageImageWidth;
}
}
}
}
else
{
// use older, not-docnet rendering method.
// uses MigraDoc rendering. Does not work with annotations, and since Migradoc
// doesn't let us know how big the image is, we can't do the image resizing, so
// we just do our best.
// render first page (eventually need to improve code to just do everything in a loop)
var paragraph = section.AddParagraph();
paragraph.Format.Alignment = ParagraphAlignment.Center;
var image = paragraph.AddImage(filePath);
image.LockAspectRatio = true;
image.Width = imageWidth; // can't be too wide now...not sure why...maybe due to margins...
image.Width = maxImageWidth; // can't be too wide now...not sure why...maybe due to margins...
image.LineFormat = imageLineFormat.Clone();
// render other PDF pages, if any
// see: https://stackoverflow.com/a/65091204/3938401
var pdfFileToAdd = PdfReader.Open(filePath, PdfDocumentOpenMode.Import);
@@ -863,20 +1013,18 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown
paragraph.Format.Alignment = ParagraphAlignment.Center;
image = paragraph.AddImage(filePath + "#" + j);
image.LockAspectRatio = true;
image.Width = imageWidth;
image.Width = maxImageWidth;
image.LineFormat = imageLineFormat.Clone();
}
}
}
LogInfo(string.Format("Added image: {0} ({1})", file.Title, filePath));
hasAddedData = true;
}
var pdfRenderer = new PdfDocumentRenderer
{
Document = pdfDoc,
WorkingDirectory = folderPath
};
LogInfo("Rendering document to PDF file...");
pdfRenderer.DocumentRenderer.PrepareDocument(); // needed if you make edits after first PrepareDocument() is called
pdfRenderer.RenderDocument();
// actually save to disk now
string outputPDFFilePath = Path.Join(outputDir, outputFileName);
LogInfo("Saving PDF document to disk...");
pdfRenderer.PdfDocument.Save(outputPDFFilePath);
+3 -4
View File
@@ -4,10 +4,10 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace MayShow.ViewModels
namespace MayShow.ViewModels;
class MainWindowViewModel : ChangeNotifier, IChangeViewModel
{
class MainWindowViewModel : ChangeNotifier, IChangeViewModel
{
BaseViewModel _currentViewModel;
Stack<BaseViewModel> _viewModels;
@@ -46,5 +46,4 @@ namespace MayShow.ViewModels
}
#endregion
}
}
+13
View File
@@ -18,6 +18,7 @@ using PdfSharp.Snippets.Font;
using MayShow.Interfaces;
using MayShow.Models;
using MayShow.Helpers;
using MayShows.Helpers;
namespace MayShow.ViewModels;
@@ -126,6 +127,18 @@ class SettingsViewModel: ChangeNotifier
}
}
public void OpenSettingsDir()
{
var topLevel = _topLevelGrabber?.GetTopLevel();
Console.WriteLine(Utilities.GetInternalDataPath());
var dirName = Utilities.GetInternalDataPath();
if (topLevel is not null && dirName != null)
{
var launcher = topLevel.Launcher;
launcher.LaunchUriAsync(new Uri(dirName));
}
}
public void Cancel()
{
DialogHost.Close("DialogHost", null);
+3 -4
View File
@@ -2,10 +2,10 @@
using MayShow.Helpers;
using MayShow.Models;
namespace MayShow.ViewModels
namespace MayShow.ViewModels;
class WarningDeleteItemViewModel : ChangeNotifier
{
class WarningDeleteItemViewModel : ChangeNotifier
{
ReportFile _file;
public WarningDeleteItemViewModel(ReportFile file)
@@ -27,5 +27,4 @@ namespace MayShow.ViewModels
{
DialogHost.Close("DialogHost", true);
}
}
}
+1 -1
View File
@@ -11,7 +11,7 @@
MaxWidth="450">
<StackPanel Orientation="Vertical"
Spacing="4">
<TextBlock Text="MayShow 1.4.0"
<TextBlock Text="MayShow 1.4.2"
HorizontalAlignment="Center"
TextWrapping="Wrap"
FontSize="18"
+3 -4
View File
@@ -5,10 +5,10 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace MayShow.Views
namespace MayShow.Views;
public partial class AboutView : UserControl
{
public partial class AboutView : UserControl
{
public AboutView()
{
this.InitializeComponent();
@@ -35,5 +35,4 @@ namespace MayShow.Views
}
LicenseTextBlock.Text = licenseText.Trim();
}
}
}
+2 -2
View File
@@ -20,12 +20,12 @@
FontSize="16"
FontWeight="Bold" />
<Label Content="Title" />
<TextBox Watermark="Title"
<TextBox PlaceholderText="Title"
Text="{Binding ClonedFile.Title}"
VerticalAlignment="Stretch"
TextWrapping="Wrap" />
<Label Content="Notes" />
<TextBox Watermark="Notes"
<TextBox PlaceholderText="Notes"
Text="{Binding ClonedFile.Notes}"
VerticalAlignment="Stretch"
AcceptsReturn="True"
+3 -4
View File
@@ -3,13 +3,12 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace MayShow.Views
namespace MayShow.Views;
public partial class EditFile : UserControl
{
public partial class EditFile : UserControl
{
public EditFile()
{
this.InitializeComponent();
}
}
}
+2 -2
View File
@@ -50,7 +50,7 @@
IsVisible="{Binding IsTitleBoxVisible}" />
<TextBox Text="{Binding ReportTitle}"
IsVisible="{Binding IsTitleBoxVisible}"
Watermark="Receipts December 2024"
PlaceholderText="Receipts December 2024"
Margin="2,0,2,4"
Classes="clearButton"
Name="TitleTextBox">
@@ -121,7 +121,7 @@
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate DataType="models:ReportFile">
<TextBox Text="{Binding Title}"
Watermark="Title"
PlaceholderText="Title"
ToolTip.Tip="{Binding Title}"
Classes="clearButton">
<TextBox.KeyBindings>
+4 -5
View File
@@ -5,10 +5,10 @@ using Avalonia.Input;
using Avalonia.Markup.Xaml;
using MayShow.ViewModels;
namespace MayShow.Views
namespace MayShow.Views;
public partial class MainView : UserControl
{
public partial class MainView : UserControl
{
public MainView()
{
this.InitializeComponent();
@@ -27,7 +27,7 @@ namespace MayShow.Views
public void UnfocusTextbox()
{
var topLevel = TopLevel.GetTopLevel(this);
topLevel?.FocusManager?.ClearFocus();
topLevel?.FocusManager?.Focus(null);
if (DataContext is MainViewModel mvm)
{
mvm?.HasUnsavedWork = true;
@@ -41,5 +41,4 @@ namespace MayShow.Views
mvm?.HasUnsavedWork = true;
}
}
}
}
+5
View File
@@ -47,6 +47,11 @@
VerticalAlignment="Top"/>
</Grid>
<CheckBox IsChecked="{Binding SaveReportJsonDataInInternalDir}">Save report data (names, notes, etc.) in MayShow settings directory (saves in working directory by default)</CheckBox>
<Button Command="{Binding OpenSettingsDir}">
<TextBlock>
<Run Text="&#xf07c;"
FontFamily="{StaticResource FontAwesomeSolid}" /> Open MayShow Settings Directory</TextBlock>
</Button>
<TextBlock TextWrapping="Wrap"
Foreground="Red"
Text="{Binding ErrorMessage}"
+3 -4
View File
@@ -3,13 +3,12 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace MayShow.Views
namespace MayShow.Views;
public partial class WarningDeleteItem : UserControl
{
public partial class WarningDeleteItem : UserControl
{
public WarningDeleteItem()
{
this.InitializeComponent();
}
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.4.0.0" name="MayShow.Desktop"/>
<assemblyIdentity version="1.4.2.0" name="MayShow.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>