Catalog/imagecatalog/MainWindow.xaml.cs

380 lines
15 KiB
C#
Raw Normal View History

using System.Windows;
using MahApps.Metro.Controls;
using ControlzEx.Theming;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using System.Windows.Media.Imaging;
using System.Diagnostics;
using Microsoft.Win32;
using System.Windows.Forms;
namespace ImageCatalog_2
{
public partial class MainWindow : MetroWindow
{
private readonly DataModel _model;
private bool _isDarkTheme = false;
public MainWindow(DataModel model)
{
InitializeComponent();
_model = model;
DataContext = _model;
// Set product version in status bar (use ProductVersion rather than AssemblyVersion)
try
{
var entry = System.Reflection.Assembly.GetEntryAssembly();
string version = string.Empty;
if (entry is not null && !string.IsNullOrEmpty(entry.Location))
{
try
{
version = FileVersionInfo.GetVersionInfo(entry.Location).ProductVersion ?? string.Empty;
}
catch { }
}
if (string.IsNullOrWhiteSpace(version))
{
// fallback to assembly version
version = entry?.GetName().Version?.ToString() ?? string.Empty;
}
VersionTextBlock.Text = string.IsNullOrWhiteSpace(version) ? string.Empty : $"v{version}";
}
catch { }
// Ensure MahApps resource dictionaries are loaded so chrome/styles are available
EnsureMahAppsResourcesLoaded();
// Apply theme based on user preference or system setting (default to light)
ApplyTheme(isDark: false);
// Subscribe to DataModel events that require UI dialogs
_model.SelectSourceFolderRequested += Model_SelectSourceFolderRequested;
_model.SelectDestinationFolderRequested += Model_SelectDestinationFolderRequested;
_model.SelectLogoFileRequested += Model_SelectLogoFileRequested;
_model.SaveSettingsRequested += Model_SaveSettingsRequested;
_model.LoadSettingsRequested += Model_LoadSettingsRequested;
_model.SelectColorRequested += Model_SelectColorRequested;
_model.SelectTransparentColorRequested += Model_SelectTransparentColorRequested;
_model.SelectModelsFolderRequested += Model_SelectModelsFolderRequested;
_model.SelectCsvOutputRequested += Model_SelectCsvOutputRequested;
// Watch for logo changes to update preview
_model.PropertyChanged += Model_PropertyChanged;
}
private void ApplyTheme(bool isDark)
{
try
{
var rd = isDark ? (ResourceDictionary)Resources["DarkTheme"] : (ResourceDictionary)Resources["LightTheme"];
foreach (var key in rd.Keys)
{
// If the theme dictionary uses suffixed keys (e.g. "WindowBackgroundBrush.Dark"),
// map them to the base key ("WindowBackgroundBrush") so existing DynamicResource lookups update.
string outKey = key?.ToString() ?? string.Empty;
if (outKey.EndsWith(".Light", StringComparison.OrdinalIgnoreCase))
outKey = outKey.Substring(0, outKey.Length - ".Light".Length);
else if (outKey.EndsWith(".Dark", StringComparison.OrdinalIgnoreCase))
outKey = outKey.Substring(0, outKey.Length - ".Dark".Length);
Resources[outKey] = rd[key];
}
}
catch
{
// ignore theme failures
}
}
private void Model_SelectModelsFolderRequested(object? sender, EventArgs e)
{
var dlg = new System.Windows.Forms.FolderBrowserDialog();
var starting = string.IsNullOrWhiteSpace(_model.ModelsFolderPath) ? Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) : _model.ModelsFolderPath;
dlg.SelectedPath = starting;
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
_model.ModelsFolderPath = dlg.SelectedPath + Path.DirectorySeparatorChar;
}
}
private void OpenModelsFolder_Click(object sender, RoutedEventArgs e)
{
try
{
var path = _model.ModelsFolderPath;
if (string.IsNullOrWhiteSpace(path)) return;
path = path.Trim().Trim('"');
if (File.Exists(path))
{
System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{path}\"");
return;
}
if (Directory.Exists(path))
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = path, UseShellExecute = true });
return;
}
}
catch { }
}
private void Model_SelectCsvOutputRequested(object? sender, EventArgs e)
{
var dlg = new Microsoft.Win32.SaveFileDialog();
dlg.Filter = "CSV file (*.csv)|*.csv|All files (*.*)|*.*";
if (!string.IsNullOrWhiteSpace(_model.CsvOutputPath)) dlg.FileName = _model.CsvOutputPath;
var result = dlg.ShowDialog(this);
if (result == true)
{
_model.CsvOutputPath = dlg.FileName;
}
}
private void OpenCsvOutputFolder_Click(object sender, RoutedEventArgs e)
{
try
{
var path = _model.CsvOutputPath;
if (string.IsNullOrWhiteSpace(path)) return;
path = path.Trim().Trim('"');
if (File.Exists(path))
{
System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{path}\"");
return;
}
var dir = Path.GetDirectoryName(path);
if (!string.IsNullOrWhiteSpace(dir) && Directory.Exists(dir))
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = dir, UseShellExecute = true });
return;
}
}
catch { }
}
private void Model_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e is null || string.IsNullOrWhiteSpace(e.PropertyName)) return;
if (e.PropertyName == nameof(_model.LogoFile))
{
UpdateLogoPreview(_model.LogoFile);
}
}
private void Model_SelectSourceFolderRequested(object? sender, EventArgs e)
{
var dlg = new System.Windows.Forms.FolderBrowserDialog();
var starting = string.IsNullOrWhiteSpace(_model.SourcePath) ? Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) : _model.SourcePath;
dlg.SelectedPath = starting;
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
_model.SourcePath = dlg.SelectedPath + Path.DirectorySeparatorChar;
}
}
private void OpenSourceFolder_Click(object sender, RoutedEventArgs e)
{
try
{
var path = _model.SourcePath;
if (string.IsNullOrWhiteSpace(path)) return;
path = path.Trim().Trim('"');
if (File.Exists(path))
{
System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{path}\"");
return;
}
if (Directory.Exists(path))
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = path, UseShellExecute = true });
return;
}
}
catch (Exception ex)
{
// ignore for now, or could show a message
}
}
private void Model_SelectDestinationFolderRequested(object? sender, EventArgs e)
{
var dlg = new System.Windows.Forms.FolderBrowserDialog();
var starting = string.IsNullOrWhiteSpace(_model.DestinationPath) ? Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) : _model.DestinationPath;
dlg.SelectedPath = starting;
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
_model.DestinationPath = dlg.SelectedPath + Path.DirectorySeparatorChar;
}
}
private void OpenDestinationFolder_Click(object sender, RoutedEventArgs e)
{
try
{
var path = _model.DestinationPath;
if (string.IsNullOrWhiteSpace(path)) return;
path = path.Trim().Trim('"');
if (File.Exists(path))
{
System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{path}\"");
return;
}
if (Directory.Exists(path))
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = path, UseShellExecute = true });
return;
}
}
catch (Exception ex)
{
// ignore for now
}
}
private void Model_SelectLogoFileRequested(object? sender, EventArgs e)
{
var dlg = new Microsoft.Win32.OpenFileDialog();
dlg.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.bmp;*.gif";
if (!string.IsNullOrWhiteSpace(_model.LogoFile)) dlg.FileName = _model.LogoFile;
var result = dlg.ShowDialog(this);
if (result == true)
{
_model.LogoFile = dlg.FileName;
}
}
private async void Model_SaveSettingsRequested(object? sender, string filePath)
{
var dlg = new Microsoft.Win32.SaveFileDialog();
dlg.Filter = "Setup (*.xml)|*.xml|All valid files (*.*)|*.*";
var result = dlg.ShowDialog(this);
if (result == true)
{
await _model.SaveSettingsToFileAsync(dlg.FileName);
}
}
private async void Model_LoadSettingsRequested(object? sender, string filePath)
{
var dlg = new Microsoft.Win32.OpenFileDialog();
dlg.Filter = "Setup (*.xml)|*.xml|All valid files (*.*)|*.*";
var result = dlg.ShowDialog(this);
if (result == true)
{
await _model.LoadSettingsFromFileAsync(dlg.FileName);
}
}
private void Model_SelectColorRequested(object? sender, EventArgs e)
{
var dlg = new System.Windows.Forms.ColorDialog { AllowFullOpen = true };
if (!string.IsNullOrWhiteSpace(_model.TextColorRGB))
{
try { dlg.Color = System.Drawing.ColorTranslator.FromHtml(_model.TextColorRGB); } catch { }
}
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
_model.TextColorRGB = System.Drawing.ColorTranslator.ToHtml(dlg.Color);
}
}
private void Model_SelectTransparentColorRequested(object? sender, EventArgs e)
{
var dlg = new System.Windows.Forms.ColorDialog { AllowFullOpen = true };
try { dlg.Color = System.Drawing.ColorTranslator.FromHtml(_model.TransparentColor); } catch { }
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
_model.TransparentColor = System.Drawing.ColorTranslator.ToHtml(dlg.Color);
}
}
private void ToggleTheme_Click(object? sender, RoutedEventArgs e)
{
ToggleTheme();
}
private void ToggleTheme()
{
try
{
_isDarkTheme = !_isDarkTheme;
// Use MahApps ThemeManager to change the application theme (handles chrome and brushes)
try
{
var themeName = _isDarkTheme ? "Dark.Blue" : "Light.Blue";
ThemeManager.Current.ChangeTheme(System.Windows.Application.Current, themeName);
}
catch
{
// Fall back silently if ThemeManager isn't available
}
// Still apply local resource overrides so any app-specific keys update
ApplyTheme(_isDarkTheme);
}
catch
{
// ignore toggle failures
}
}
private void EnsureMahAppsResourcesLoaded()
{
try
{
var app = System.Windows.Application.Current;
if (app is null)
return;
var mds = app.Resources.MergedDictionaries;
// Helper to add if missing
void AddIfMissing(string uriString)
{
if (!mds.Any(d => d.Source is not null && d.Source.OriginalString.Equals(uriString, StringComparison.OrdinalIgnoreCase)))
{
mds.Add(new ResourceDictionary { Source = new Uri(uriString) });
}
}
AddIfMissing("pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml");
AddIfMissing("pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml");
// Ensure a default theme is present
if (!mds.Any(d => d.Source is not null && d.Source.OriginalString.IndexOf("/MahApps.Metro;component/Styles/Themes/", StringComparison.OrdinalIgnoreCase) >= 0))
{
AddIfMissing("pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml");
_isDarkTheme = false;
}
}
catch
{
// ignore; styling will fallback to local resources
}
}
private void UpdateLogoPreview(string? path)
{
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
{
LogoPreview.Source = null;
return;
}
try
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.UriSource = new Uri(path);
bitmap.EndInit();
LogoPreview.Source = bitmap;
}
catch
{
LogoPreview.Source = null;
}
}
}
}