diff --git a/App.axaml.cs b/App.axaml.cs --- a/App.axaml.cs +++ b/App.axaml.cs @@ -29,6 +29,15 @@ namespace DesertPaintCodex ShowWelcomeView(); CloseMainWindow(); } + + public void RefreshMainWindow() + { + if (ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return; + + desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown; + CloseMainWindow(); + ShowMainWindow(); + } private void ShowWelcomeView() { diff --git a/Models/PlayerProfile.cs b/Models/PlayerProfile.cs --- a/Models/PlayerProfile.cs +++ b/Models/PlayerProfile.cs @@ -2,6 +2,7 @@ using System.IO; using System.IO.Compression; using System.Collections.Generic; +using System.Diagnostics; using System.Text.RegularExpressions; using DesertPaintCodex.Util; using DesertPaintCodex.Services; @@ -127,13 +128,13 @@ namespace DesertPaintCodex.Models public static void ConvertFromPP(string ppFile, string dpFile) { using StreamReader reader = new(ppFile); - using StreamWriter writer = new(dpFile); + using StreamWriter writer = new(dpFile, false); string? line; while ((line = reader.ReadLine()) != null) { string[] tokens = line.Split('|'); //if ((tokens.Length > 0) && (tokens [0] != "//")) - if ((tokens.Length != 5) && (tokens[0].Trim() != "//")) + if ((tokens.Length == 5) && (tokens[0].Trim() != "//")) { string reagent1 = tokens[0].Trim(); string reagent2 = tokens[1].Trim(); @@ -239,15 +240,14 @@ namespace DesertPaintCodex.Models return true; } - public void ImportFromPP(string importDir) + public void ImportFromPP(string reactionsFile) { // Convert old file. - ConvertFromPP( - Path.Combine(importDir, "reactions.txt"), - _reactFile); + ConvertFromPP(reactionsFile, _reactFile); try { // If there is an ingredients file, move it in. + string importDir = Path.GetDirectoryName(reactionsFile) ?? ""; File.Copy( Path.Combine(importDir, "ingredients.txt"), Path.Combine(Directory, "ingredients.txt"), @@ -261,7 +261,12 @@ namespace DesertPaintCodex.Models public void Import(string file) { - ZipFile.ExtractToDirectory(file, Directory); + if (!File.Exists(file)) + { + Debug.WriteLine("Import file does not exist: " + file); + // TODO: Show message dialog. + } + ZipFile.ExtractToDirectory(file, Directory, true); } public void Export(string file) diff --git a/Services/PaletteService.cs b/Services/PaletteService.cs --- a/Services/PaletteService.cs +++ b/Services/PaletteService.cs @@ -24,6 +24,8 @@ namespace DesertPaintCodex.Services Debug.Assert(colorsPath != null); Load(colorsPath); + + _initialized = true; } public static void Load(string file) diff --git a/Services/ProfileManager.cs b/Services/ProfileManager.cs --- a/Services/ProfileManager.cs +++ b/Services/ProfileManager.cs @@ -51,6 +51,12 @@ namespace DesertPaintCodex.Services return CurrentProfile; } + public static void ReloadProfile() + { + if (CurrentProfile == null) return; + LoadProfile(CurrentProfile.Name); + } + public static PlayerProfile CreateNewProfile(string name) { CurrentProfile = new PlayerProfile(name, Path.Combine(FileUtils.AppDataPath, name)); diff --git a/ViewModels/MainWindowViewModel.cs b/ViewModels/MainWindowViewModel.cs --- a/ViewModels/MainWindowViewModel.cs +++ b/ViewModels/MainWindowViewModel.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reactive; @@ -17,12 +18,22 @@ namespace DesertPaintCodex.ViewModels public class MainWindowViewModel : ViewModelBase { private string _statusText = string.Empty; - public string StatusText { get => _statusText; private set => this.RaiseAndSetIfChanged(ref _statusText, value); } + + public string StatusText + { + get => _statusText; + private set => this.RaiseAndSetIfChanged(ref _statusText, value); + } + + private static readonly List ZipFileExtensions = new() {"zip"}; + private static readonly FileDialogFilter ZipFileFilter = new() {Extensions = ZipFileExtensions, Name = "Zip"}; + private static readonly List ZipFileFilters = new() {ZipFileFilter}; + + private static readonly List TxtFileExtensions = new() {"txt"}; + private static readonly FileDialogFilter TxtFileFilter = new() {Extensions = TxtFileExtensions, Name = "Text"}; + private static readonly List TxtFileFilters = new() {TxtFileFilter}; - private static readonly List ZipFileExtensions = new() { $"*.zip;" }; - private static readonly FileDialogFilter ZipDialogFilter = new() {Extensions = ZipFileExtensions}; - private static readonly List ZipDialogFilters = new() { ZipDialogFilter }; - private static readonly List NoFilters = new(); + private static readonly List NoFileFilters = new(); public MainWindowViewModel() { @@ -53,36 +64,93 @@ namespace DesertPaintCodex.ViewModels } } - public static async void ImportProfile() + public async void ImportProfile() { - string? fileName = await GetLoadFileName("Open Zipped Profile", ZipDialogFilters); - if (!string.IsNullOrEmpty(fileName)) + string? fileName = await GetLoadFileName("Open Zipped Profile", ZipFileFilters); + + if (string.IsNullOrEmpty(fileName)) return; + + try { ProfileManager.CurrentProfile?.Import(fileName); } + catch (Exception e) + { + Debug.WriteLine("ImportProfile threw exception " + e); + await ShowMessageBox("Import Failed", + "Your file could not be imported. It must be a zip file containing a Desert Paint Codex profile.", "OK"); + } + + ProfileManager.ReloadProfile(); + + if (Application.Current is not App app) return; + + app.RefreshMainWindow(); + } + + public async void ExportProfile() + { + string? fileName = await GetSaveFileName("Save Zipped Profile", ZipFileFilters); + + if (string.IsNullOrEmpty(fileName)) return; + + try + { + ProfileManager.CurrentProfile?.Export(fileName); + } + catch (Exception e) + { + Debug.WriteLine("ExportProfile threw exception " + e); + await ShowMessageBox("Export Failed", + "Your profile could not be exported. Please ensure that you are providing a valid filename for the zip file that we are creating.", "OK"); + } } - public static async void ExportProfile() + public async void ExportForPP(object f) { - string? fileName = await GetSaveFileName("Save Zipped Profile", ZipDialogFilters); - if (!string.IsNullOrEmpty(fileName)) + string? fileName = await GetSaveFileName("Save Practical Paint File", TxtFileFilters, "reactions.txt"); + + if (string.IsNullOrEmpty(fileName)) return; + + try { - ProfileManager.CurrentProfile?.Import(fileName); + ProfileManager.CurrentProfile?.SaveToPP(fileName); + } + catch (Exception e) + { + Debug.WriteLine("ExportForPP threw exception " + e); + await ShowMessageBox("Export Failed", + "Please ensure that you have provided a valid file path for your reactions file.", "OK"); } } - public static async void ExportForPP() + public async void ImportFromPP() { - string? fileName = await GetSaveFileName("Save Practical Paint File", NoFilters); - if (!string.IsNullOrEmpty(fileName)) + string? fileName = await GetLoadFileName("Import Reactions File", TxtFileFilters, "reactions.txt"); + + if (string.IsNullOrEmpty(fileName)) return; + + try + { + ProfileManager.CurrentProfile?.ImportFromPP(fileName); + } + catch (Exception e) { - ProfileManager.CurrentProfile?.SaveToPP(fileName); + Debug.WriteLine("ImportFromPP threw exception " + e); + await ShowMessageBox("Import Failed", + "Your file could not be imported. It must be a valid Practical Paint reactions.txt file.", "OK"); } + + ProfileManager.ReloadProfile(); + + if (Application.Current is not App app) return; + + app.RefreshMainWindow(); } public static async void ExportPaintRecipes() { - string? fileName = await GetSaveFileName("Export Paint Recipes", NoFilters); + string? fileName = await GetSaveFileName("Export Paint Recipes", NoFileFilters); if (!string.IsNullOrEmpty(fileName)) { ProfileManager.CurrentProfile?.ExportWikiRecipes(fileName); @@ -91,7 +159,7 @@ namespace DesertPaintCodex.ViewModels public static async void ExportRibbonRecipes() { - string? fileName = await GetSaveFileName("Export Ribbon Recipes", NoFilters); + string? fileName = await GetSaveFileName("Export Ribbon Recipes", NoFileFilters); if (!string.IsNullOrEmpty(fileName)) { ProfileManager.CurrentProfile?.ExportWikiRibbons(fileName); @@ -136,7 +204,7 @@ namespace DesertPaintCodex.ViewModels return true; } - private static async Task GetLoadFileName(string title, List filters) + private static async Task GetLoadFileName(string title, List filters, string? fileName = null) { if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return null; @@ -144,9 +212,10 @@ namespace DesertPaintCodex.ViewModels OpenFileDialog dialog = new() { - Title = title, - Filters = NoFilters, // filters, - AllowMultiple = false + Title = title, + Filters = filters, + InitialFileName = fileName, + AllowMultiple = false }; string[] files = await dialog.ShowAsync(desktop.MainWindow); @@ -154,7 +223,7 @@ namespace DesertPaintCodex.ViewModels } - private static async Task GetSaveFileName(string title, List filters) + private static async Task GetSaveFileName(string title, List filters, string? fileName = null) { if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return null; @@ -162,8 +231,9 @@ namespace DesertPaintCodex.ViewModels SaveFileDialog dialog = new() { - Title = title, - Filters = NoFilters, // filters + Title = title, + Filters = filters, + InitialFileName = fileName }; return await dialog.ShowAsync(desktop.MainWindow); diff --git a/Views/MainWindow.axaml b/Views/MainWindow.axaml --- a/Views/MainWindow.axaml +++ b/Views/MainWindow.axaml @@ -61,6 +61,7 @@ + Will overwrite the current profile with a profile from a zipped folder. @@ -71,13 +72,19 @@ Will export the current profile to a zipped folder. - + + + + Will import a Practical Paint reactions file, replacing this profile's reactions. + + + Will generate a Practical Paint reactions file from the current profile. - + @@ -89,6 +96,7 @@ Exports recipes in Wiki table format. + Copies recipes in Wiki table format.