Add image processing benchmarks and UI folder open buttons

- Added MaddoShared.Benchmarks project with BenchmarkDotNet for comprehensive image processing performance tests (parallel, chunk, size, stress).
- Included helper for generating test images and custom configs to ensure InProcess toolchain for .NET Windows compatibility.
- Added cross-platform scripts to run benchmarks easily.
- Updated .gitignore for benchmark artifacts and temp files.
- Exposed GetFilesToProcessPublic in ImageCreationStuff for testability.
- Added file name sanitization in ImageCreatorSharp to prevent IO errors.
- Enhanced WinForms UI: added "Open" buttons for source/destination folders, handled folder opening in Explorer, and improved user messaging and layout.
- Updated solution file to include new benchmark project.
This commit is contained in:
MaddoScientisto 2026-02-14 19:20:25 +01:00
commit c2fd4bf780
17 changed files with 1608 additions and 301 deletions

View file

@ -1010,6 +1010,8 @@ namespace ImageCatalog_2
public event EventHandler<string> SaveSettingsRequested;
public event EventHandler<string> LoadSettingsRequested;
public event EventHandler SelectColorRequested;
// Request that the View shows a message to the user (message, caption, icon)
public event EventHandler<Tuple<string, string, MessageBoxIcon>> ShowMessageRequested;
private void SelectSourceFolder(object parameter)
{

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,7 @@ using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
@ -47,6 +48,10 @@ public partial class MainForm
BindControls();
// Wire up 'Open folder in Explorer' buttons
btnOpenSourceFolder.Click += BtnOpenSourceFolder_Click;
btnOpenDestFolder.Click += BtnOpenDestFolder_Click;
var version = Assembly.GetExecutingAssembly().GetName().Version;
_Label27.Text = $"Version: {version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
}
@ -70,6 +75,21 @@ public partial class MainForm
Model.SaveSettingsRequested += OnSaveSettingsRequested;
Model.LoadSettingsRequested += OnLoadSettingsRequested;
Model.SelectColorRequested += OnSelectColorRequested;
// Show message requests (from ViewModel validation)
Model.ShowMessageRequested += OnShowMessageRequested;
}
private void OnShowMessageRequested(object? sender, Tuple<string, string, MessageBoxIcon> args)
{
if (args is null) return;
// Ensure call on UI thread
if (InvokeRequired)
{
Invoke(new Action(() => OnShowMessageRequested(sender, args)));
return;
}
MessageBox.Show(this, args.Item1, args.Item2, MessageBoxButtons.OK, args.Item3);
}
private void SetDefaults()
@ -181,6 +201,57 @@ public partial class MainForm
}
}
private void BtnOpenSourceFolder_Click(object? sender, EventArgs e)
{
// Prefer the model value but fall back to the textbox if needed
var path = string.IsNullOrWhiteSpace(Model.SourcePath) ? txtSorgente.Text : Model.SourcePath;
OpenFolder(path);
}
private void BtnOpenDestFolder_Click(object? sender, EventArgs e)
{
var path = string.IsNullOrWhiteSpace(Model.DestinationPath) ? txtDestinazione.Text : Model.DestinationPath;
OpenFolder(path);
}
private void OpenFolder(string? path)
{
if (string.IsNullOrWhiteSpace(path))
{
MessageBox.Show(this, "Folder path is empty.", "Open Folder", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
path = path.Trim().Trim('"');
try
{
if (File.Exists(path))
{
// If a file was provided, open its folder and select it
Process.Start("explorer.exe", $"/select,\"{path}\"");
return;
}
if (Directory.Exists(path))
{
Process.Start(new ProcessStartInfo
{
FileName = path,
UseShellExecute = true
});
return;
}
MessageBox.Show(this, $"Folder does not exist: {path}", "Open Folder", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
catch (Exception ex)
{
_logger?.LogError(ex, "Failed to open folder {Path}", path);
MessageBox.Show(this, $"Failed to open folder: {ex.Message}", "Open Folder", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void OnSelectDestinationFolderRequested(object sender, EventArgs e)
{
var dialogResult = SelectFolder(Model.DestinationPath);