From 70f7c2eec91111cabf3ce1f22d0ff55bc129dc14 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 16:32:32 +0100 Subject: [PATCH 01/13] unsaved indicator --- .../RegistryPreviewMainPage.Events.cs | 4 +++ .../RegistryPreviewMainPage.Utilities.cs | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs index 0df3a5c0f5ed..8d840ea08524 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs @@ -112,6 +112,7 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) case ContentDialogResult.Secondary: // Don't save and continue the file open! saveButton.IsEnabled = false; + UpdateUnsavedFileIndicator(false); break; default: // Don't open the new file! @@ -143,6 +144,7 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) // disable the Save button as it's a new file saveButton.IsEnabled = false; + UpdateUnsavedFileIndicator(false); // Restore the event handler as we're loaded MonacoEditor.TextChanged += MonacoEditor_TextChanged; @@ -193,6 +195,7 @@ private async void RefreshButton_Click(object sender, RoutedEventArgs e) UpdateToolBarAndUI(await OpenRegistryFile(_appFileName), true, true); saveButton.IsEnabled = false; + UpdateUnsavedFileIndicator(false); // restore the TextChanged handler MonacoEditor.TextChanged += MonacoEditor_TextChanged; @@ -355,6 +358,7 @@ private void MonacoEditor_TextChanged(object sender, EventArgs e) { RefreshRegistryFile(); saveButton.IsEnabled = true; + UpdateUnsavedFileIndicator(true); }); } } diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index b8fc6e4e1d9a..6f0e59fff435 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Reflection; using System.Text; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Microsoft.UI.Input; @@ -22,6 +23,9 @@ namespace RegistryPreviewUILib { public sealed partial class RegistryPreviewMainPage : Page { + private static readonly string _usavedFileIndicator = "* "; + private static readonly char[] _usavedFileIndicatorChars = [' ', '*']; + private static SemaphoreSlim _dialogSemaphore = new(1); private string lastKeyPath; @@ -834,6 +838,7 @@ private async void HandleDirtyClosing(string title, string content, string prima break; case ContentDialogResult.Secondary: // Don't save, and then close! + UpdateUnsavedFileIndicator(false); saveButton.IsEnabled = false; break; default: @@ -902,6 +907,25 @@ public void ChangeCursor(UIElement uiElement, bool wait) type.InvokeMember("ProtectedCursor", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, uiElement, new object[] { cursor }, CultureInfo.InvariantCulture); } + public void UpdateUnsavedFileIndicator(bool show) + { + // get and cut current title + string currentTitel = Regex.Replace(_mainWindow.Title, APPNAME + @"$|\s-\s" + APPNAME + @"$", string.Empty); + + // verify + bool titleContiansIndicator = currentTitel.StartsWith(_usavedFileIndicator, StringComparison.CurrentCultureIgnoreCase); + + // update + if (!titleContiansIndicator && show) + { + _updateWindowTitleFunction(_usavedFileIndicator + currentTitel); + } + else if (titleContiansIndicator && !show) + { + _updateWindowTitleFunction(currentTitel.TrimStart(_usavedFileIndicatorChars)); + } + } + /// /// Wrapper method that saves the current file in place, using the current text in editor. /// @@ -930,6 +954,7 @@ private void SaveFile() streamWriter.Close(); // only change when the save is successful + UpdateUnsavedFileIndicator(false); saveButton.IsEnabled = false; } catch (UnauthorizedAccessException ex) From 36629362e4064f578cf35b4bf5dd400cbe834093 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 16:43:15 +0100 Subject: [PATCH 02/13] save as behavior for svae button --- .../RegistryPreviewMainPage.Events.cs | 21 ++++++++++++ .../RegistryPreviewMainPage.Utilities.cs | 32 ++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs index 8d840ea08524..23f0f76fe84b 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs @@ -156,7 +156,28 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) /// private void SaveButton_Click(object sender, RoutedEventArgs e) { + if (string.IsNullOrEmpty(_appFileName)) + { + // Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's + // called while running as admin + IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow); + string filename = SaveFilePicker.ShowDialog( + windowHandle, + resourceLoader.GetString("SuggestFileName"), + resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0', + resourceLoader.GetString("SaveDialogTitle")); + + if (filename == string.Empty) + { + return; + } + + _appFileName = filename; + } + + // save and update window title SaveFile(); + _updateWindowTitleFunction(_appFileName); } /// diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index 6f0e59fff435..00c786f1333d 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -834,7 +834,12 @@ private async void HandleDirtyClosing(string title, string content, string prima { case ContentDialogResult.Primary: // Save, then close - SaveFile(); + if (!DirtyCloseSaveFile()) + { + // save cancelled + return; + } + break; case ContentDialogResult.Secondary: // Don't save, and then close! @@ -850,6 +855,31 @@ private async void HandleDirtyClosing(string title, string content, string prima Application.Current.Exit(); } + private bool DirtyCloseSaveFile() + { + if (string.IsNullOrEmpty(_appFileName)) + { + // Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's + // called while running as admin + IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow); + string filename = SaveFilePicker.ShowDialog( + windowHandle, + resourceLoader.GetString("SuggestFileName"), + resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0', + resourceLoader.GetString("SaveDialogTitle")); + + if (filename == string.Empty) + { + return false; + } + + _appFileName = filename; + } + + SaveFile(); + return true; + } + /// /// Method will open the Registry Editor or merge the current REG file into the Registry via the Editor /// Process will prompt for elevation if it needs it. From c2887531f1aa4ce18bcccc87fcc7e9a6c83644c2 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 17:03:07 +0100 Subject: [PATCH 03/13] correctly handle file save errors --- .../RegistryPreviewMainPage.Events.cs | 18 ++++++++++++++---- .../RegistryPreviewMainPage.Utilities.cs | 14 +++++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs index 23f0f76fe84b..d6f6c1092739 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs @@ -107,7 +107,12 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) { case ContentDialogResult.Primary: // Save, then continue the file open - SaveFile(); + bool success = SaveFile(); + if (!success) + { + return; + } + break; case ContentDialogResult.Secondary: // Don't save and continue the file open! @@ -176,7 +181,7 @@ private void SaveButton_Click(object sender, RoutedEventArgs e) } // save and update window title - SaveFile(); + _ = SaveFile(); _updateWindowTitleFunction(_appFileName); } @@ -200,7 +205,7 @@ private async void SaveAsButton_Click(object sender, RoutedEventArgs e) } _appFileName = filename; - SaveFile(); + _ = SaveFile(); UpdateToolBarAndUI(await OpenRegistryFile(_appFileName)); } @@ -281,7 +286,12 @@ private async void WriteButton_Click(object sender, RoutedEventArgs e) { case ContentDialogResult.Primary: // Save, then continue the file open - SaveFile(); + bool success = SaveFile(); + if (!success) + { + return; + } + break; case ContentDialogResult.Secondary: // Don't save and continue the file open! diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index 00c786f1333d..412f75b97acb 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -876,8 +876,8 @@ private bool DirtyCloseSaveFile() _appFileName = filename; } - SaveFile(); - return true; + bool r = SaveFile(); + return r; } /// @@ -959,8 +959,10 @@ public void UpdateUnsavedFileIndicator(bool show) /// /// Wrapper method that saves the current file in place, using the current text in editor. /// - private void SaveFile() + private bool SaveFile() { + bool saveSuccess = true; + ChangeCursor(gridPreview, true); // set up the FileStream for all writing @@ -989,6 +991,8 @@ private void SaveFile() } catch (UnauthorizedAccessException ex) { + saveSuccess = false; + // this exception is thrown if the file is there but marked as read only ShowMessageBox( resourceLoader.GetString("ErrorDialogTitle"), @@ -997,6 +1001,8 @@ private void SaveFile() } catch { + saveSuccess = false; + // this catch handles all other exceptions thrown when trying to write the file out ShowMessageBox( resourceLoader.GetString("ErrorDialogTitle"), @@ -1014,6 +1020,8 @@ private void SaveFile() // restore the cursor ChangeCursor(gridPreview, false); + + return saveSuccess; } /// From 410c37fef3fb4a864851715fc9528380b2f8fb78 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 17:19:02 +0100 Subject: [PATCH 04/13] fix wrong unsaved state after opening file --- .../RegistryPreviewMainPage.Events.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs index d6f6c1092739..0770d0ee2c1c 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs @@ -23,6 +23,9 @@ public sealed partial class RegistryPreviewMainPage : Page { private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); + // Indicator if we loaded or reloaded a file + private static bool newFileLoaded; + /// /// Event that is will prevent the app from closing if the "save file" flag is active /// @@ -144,6 +147,9 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) { // mute the TextChanged handler to make for clean UI MonacoEditor.TextChanged -= MonacoEditor_TextChanged; + newFileLoaded = true; + + // update file name _appFileName = storageFile.Path; UpdateToolBarAndUI(await OpenRegistryFile(_appFileName)); @@ -215,6 +221,7 @@ private async void SaveAsButton_Click(object sender, RoutedEventArgs e) private async void RefreshButton_Click(object sender, RoutedEventArgs e) { // mute the TextChanged handler to make for clean UI + newFileLoaded = true; MonacoEditor.TextChanged -= MonacoEditor_TextChanged; // reload the current Registry file and update the toolbar accordingly. @@ -388,8 +395,13 @@ private void MonacoEditor_TextChanged(object sender, EventArgs e) _dispatcherQueue.TryEnqueue(() => { RefreshRegistryFile(); - saveButton.IsEnabled = true; - UpdateUnsavedFileIndicator(true); + if (!newFileLoaded) + { + saveButton.IsEnabled = true; + UpdateUnsavedFileIndicator(true); + } + + newFileLoaded = false; }); } } From 7dfadaf42283c8cb79e08cdd05a93fbe443cbe9c Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 17:28:57 +0100 Subject: [PATCH 05/13] make spell check happy --- .../RegistryPreviewMainPage.Utilities.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index 412f75b97acb..32d87503704c 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -23,8 +23,8 @@ namespace RegistryPreviewUILib { public sealed partial class RegistryPreviewMainPage : Page { - private static readonly string _usavedFileIndicator = "* "; - private static readonly char[] _usavedFileIndicatorChars = [' ', '*']; + private static readonly string _unsavedFileIndicator = "* "; + private static readonly char[] _unsavedFileIndicatorChars = [' ', '*']; private static SemaphoreSlim _dialogSemaphore = new(1); private string lastKeyPath; @@ -940,19 +940,19 @@ public void ChangeCursor(UIElement uiElement, bool wait) public void UpdateUnsavedFileIndicator(bool show) { // get and cut current title - string currentTitel = Regex.Replace(_mainWindow.Title, APPNAME + @"$|\s-\s" + APPNAME + @"$", string.Empty); + string currentTitle = Regex.Replace(_mainWindow.Title, APPNAME + @"$|\s-\s" + APPNAME + @"$", string.Empty); // verify - bool titleContiansIndicator = currentTitel.StartsWith(_usavedFileIndicator, StringComparison.CurrentCultureIgnoreCase); + bool titleContainsIndicator = currentTitle.StartsWith(_unsavedFileIndicator, StringComparison.CurrentCultureIgnoreCase); // update - if (!titleContiansIndicator && show) + if (!titleContainsIndicator && show) { - _updateWindowTitleFunction(_usavedFileIndicator + currentTitel); + _updateWindowTitleFunction(_unsavedFileIndicator + currentTitle); } - else if (titleContiansIndicator && !show) + else if (titleContainsIndicator && !show) { - _updateWindowTitleFunction(currentTitel.TrimStart(_usavedFileIndicatorChars)); + _updateWindowTitleFunction(currentTitle.TrimStart(_unsavedFileIndicatorChars)); } } From 402064b1d3841434ea627cdc56939a23a288992f Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 17:57:27 +0100 Subject: [PATCH 06/13] code cleanup --- .../RegistryPreviewMainPage.Events.cs | 38 +++--------- .../RegistryPreviewMainPage.Utilities.cs | 58 ++++++++++--------- 2 files changed, 38 insertions(+), 58 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs index 0770d0ee2c1c..315424b82aff 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs @@ -110,8 +110,8 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) { case ContentDialogResult.Primary: // Save, then continue the file open - bool success = SaveFile(); - if (!success) + if (!AskFileName(false) || + !SaveFile()) { return; } @@ -167,23 +167,9 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) /// private void SaveButton_Click(object sender, RoutedEventArgs e) { - if (string.IsNullOrEmpty(_appFileName)) + if (!AskFileName(false)) { - // Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's - // called while running as admin - IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow); - string filename = SaveFilePicker.ShowDialog( - windowHandle, - resourceLoader.GetString("SuggestFileName"), - resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0', - resourceLoader.GetString("SaveDialogTitle")); - - if (filename == string.Empty) - { - return; - } - - _appFileName = filename; + return; } // save and update window title @@ -196,21 +182,11 @@ private void SaveButton_Click(object sender, RoutedEventArgs e) /// private async void SaveAsButton_Click(object sender, RoutedEventArgs e) { - // Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's - // called while running as admin - IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow); - string filename = SaveFilePicker.ShowDialog( - windowHandle, - resourceLoader.GetString("SuggestFileName"), - resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0', - resourceLoader.GetString("SaveDialogTitle")); - - if (filename == string.Empty) + if (!AskFileName(true)) { return; } - _appFileName = filename; _ = SaveFile(); UpdateToolBarAndUI(await OpenRegistryFile(_appFileName)); } @@ -293,8 +269,8 @@ private async void WriteButton_Click(object sender, RoutedEventArgs e) { case ContentDialogResult.Primary: // Save, then continue the file open - bool success = SaveFile(); - if (!success) + if (!AskFileName(false) || + !SaveFile()) { return; } diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index 32d87503704c..704f3ffc0583 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -834,9 +834,9 @@ private async void HandleDirtyClosing(string title, string content, string prima { case ContentDialogResult.Primary: // Save, then close - if (!DirtyCloseSaveFile()) + if (!AskFileName(false) || + !SaveFile()) { - // save cancelled return; } @@ -855,31 +855,6 @@ private async void HandleDirtyClosing(string title, string content, string prima Application.Current.Exit(); } - private bool DirtyCloseSaveFile() - { - if (string.IsNullOrEmpty(_appFileName)) - { - // Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's - // called while running as admin - IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow); - string filename = SaveFilePicker.ShowDialog( - windowHandle, - resourceLoader.GetString("SuggestFileName"), - resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0', - resourceLoader.GetString("SaveDialogTitle")); - - if (filename == string.Empty) - { - return false; - } - - _appFileName = filename; - } - - bool r = SaveFile(); - return r; - } - /// /// Method will open the Registry Editor or merge the current REG file into the Registry via the Editor /// Process will prompt for elevation if it needs it. @@ -956,6 +931,35 @@ public void UpdateUnsavedFileIndicator(bool show) } } + /// + /// Ask the user for the file path if it is unknown because of an unsaved file + /// + /// Ask regardless of the known file name in case of save as action. + /// Returns true if user selected a path, otherwise false + public bool AskFileName(bool askAlways) + { + if (string.IsNullOrEmpty(_appFileName) || askAlways ) + { + // Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's + // called while running as admin + IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow); + string filename = SaveFilePicker.ShowDialog( + windowHandle, + resourceLoader.GetString("SuggestFileName"), + resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0', + resourceLoader.GetString("SaveDialogTitle")); + + if (filename == string.Empty) + { + return false; + } + + _appFileName = filename; + } + + return true; + } + /// /// Wrapper method that saves the current file in place, using the current text in editor. /// From 609faa7408a15c94deea87cf2fdd5287baa972b1 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 18:17:03 +0100 Subject: [PATCH 07/13] different code fixes --- .../RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs | 6 ++---- .../RegistryPreviewMainPage.Utilities.cs | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs index 315424b82aff..a928cd23cc78 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs @@ -23,7 +23,7 @@ public sealed partial class RegistryPreviewMainPage : Page { private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); - // Indicator if we loaded or reloaded a file + // Indicator if we loaded/reloaded/saved a file and need to skip TextChangedEevent one time. private static bool newFileLoaded; /// @@ -174,7 +174,6 @@ private void SaveButton_Click(object sender, RoutedEventArgs e) // save and update window title _ = SaveFile(); - _updateWindowTitleFunction(_appFileName); } /// @@ -182,12 +181,11 @@ private void SaveButton_Click(object sender, RoutedEventArgs e) /// private async void SaveAsButton_Click(object sender, RoutedEventArgs e) { - if (!AskFileName(true)) + if (!AskFileName(true) || !SaveFile()) { return; } - _ = SaveFile(); UpdateToolBarAndUI(await OpenRegistryFile(_appFileName)); } diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index 704f3ffc0583..73353c16c2f5 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -62,6 +62,7 @@ private async Task OpenRegistryFile(string filename) // update the current window's title with the current filename _updateWindowTitleFunction(filename); + UpdateUnsavedFileIndicator(false); // Load in the whole file in one call and plop it all into editor FileStream fileStream = null; @@ -990,6 +991,7 @@ private bool SaveFile() streamWriter.Close(); // only change when the save is successful + _updateWindowTitleFunction(_appFileName); UpdateUnsavedFileIndicator(false); saveButton.IsEnabled = false; } From f95bb4366275a1c4aae227ec9afb0eb38426ef08 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 18:20:04 +0100 Subject: [PATCH 08/13] code cleanup --- .../RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index 73353c16c2f5..032857a4e47f 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -62,7 +62,6 @@ private async Task OpenRegistryFile(string filename) // update the current window's title with the current filename _updateWindowTitleFunction(filename); - UpdateUnsavedFileIndicator(false); // Load in the whole file in one call and plop it all into editor FileStream fileStream = null; @@ -992,7 +991,6 @@ private bool SaveFile() // only change when the save is successful _updateWindowTitleFunction(_appFileName); - UpdateUnsavedFileIndicator(false); saveButton.IsEnabled = false; } catch (UnauthorizedAccessException ex) From 7b22a197d2fa03134a46a796d5b87a159d39faa2 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 18:30:51 +0100 Subject: [PATCH 09/13] reuse file name --- .../RegistryPreviewMainPage.Events.cs | 8 ++++---- .../RegistryPreviewMainPage.Utilities.cs | 12 +++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs index a928cd23cc78..6b499853f2fd 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs @@ -110,7 +110,7 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) { case ContentDialogResult.Primary: // Save, then continue the file open - if (!AskFileName(false) || + if (!AskFileName(_appFileName) || !SaveFile()) { return; @@ -167,7 +167,7 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) /// private void SaveButton_Click(object sender, RoutedEventArgs e) { - if (!AskFileName(false)) + if (!AskFileName(_appFileName)) { return; } @@ -181,7 +181,7 @@ private void SaveButton_Click(object sender, RoutedEventArgs e) /// private async void SaveAsButton_Click(object sender, RoutedEventArgs e) { - if (!AskFileName(true) || !SaveFile()) + if (!AskFileName(_appFileName) || !SaveFile()) { return; } @@ -267,7 +267,7 @@ private async void WriteButton_Click(object sender, RoutedEventArgs e) { case ContentDialogResult.Primary: // Save, then continue the file open - if (!AskFileName(false) || + if (!AskFileName(_appFileName) || !SaveFile()) { return; diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index 032857a4e47f..e9d078d1d4e5 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -834,7 +834,7 @@ private async void HandleDirtyClosing(string title, string content, string prima { case ContentDialogResult.Primary: // Save, then close - if (!AskFileName(false) || + if (!AskFileName(_appFileName) || !SaveFile()) { return; @@ -934,18 +934,20 @@ public void UpdateUnsavedFileIndicator(bool show) /// /// Ask the user for the file path if it is unknown because of an unsaved file /// - /// Ask regardless of the known file name in case of save as action. + /// If not empty always aks for a file path and use the value as name. /// Returns true if user selected a path, otherwise false - public bool AskFileName(bool askAlways) + public bool AskFileName(string fileName) { - if (string.IsNullOrEmpty(_appFileName) || askAlways ) + if (string.IsNullOrEmpty(_appFileName) || !string.IsNullOrEmpty(fileName) ) { + string fName = string.IsNullOrEmpty(fileName) ? resourceLoader.GetString("SuggestFileName") : fileName; + // Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's // called while running as admin IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow); string filename = SaveFilePicker.ShowDialog( windowHandle, - resourceLoader.GetString("SuggestFileName"), + fName, resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0', resourceLoader.GetString("SaveDialogTitle")); From 0128d5c9d5d6aa7434cc8b1755efd2b683b5bba5 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 18:36:14 +0100 Subject: [PATCH 10/13] make spell checker happy --- .../RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs index 6b499853f2fd..b64c46d3e33b 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs @@ -23,7 +23,7 @@ public sealed partial class RegistryPreviewMainPage : Page { private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); - // Indicator if we loaded/reloaded/saved a file and need to skip TextChangedEevent one time. + // Indicator if we loaded/reloaded/saved a file and need to skip TextChanged event one time. private static bool newFileLoaded; /// From 9a812c4feb40567eb9002c9042226bced5b24bb7 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 21:08:36 +0100 Subject: [PATCH 11/13] fix typo --- .../RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index e9d078d1d4e5..5edab65f9c75 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -934,7 +934,7 @@ public void UpdateUnsavedFileIndicator(bool show) /// /// Ask the user for the file path if it is unknown because of an unsaved file /// - /// If not empty always aks for a file path and use the value as name. + /// If not empty always ask for a file path and use the value as name. /// Returns true if user selected a path, otherwise false public bool AskFileName(string fileName) { From f91bf787242d833bea50a475934604a16dfb9fac Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 21:23:16 +0100 Subject: [PATCH 12/13] fixes --- .../RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs | 7 ++++--- .../RegistryPreviewMainPage.Utilities.cs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs index b64c46d3e33b..5f490f205bb4 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs @@ -110,7 +110,7 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) { case ContentDialogResult.Primary: // Save, then continue the file open - if (!AskFileName(_appFileName) || + if (!AskFileName(string.Empty) || !SaveFile()) { return; @@ -167,7 +167,7 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) /// private void SaveButton_Click(object sender, RoutedEventArgs e) { - if (!AskFileName(_appFileName)) + if (!AskFileName(string.Empty)) { return; } @@ -181,6 +181,7 @@ private void SaveButton_Click(object sender, RoutedEventArgs e) /// private async void SaveAsButton_Click(object sender, RoutedEventArgs e) { + newFileLoaded = true; if (!AskFileName(_appFileName) || !SaveFile()) { return; @@ -267,7 +268,7 @@ private async void WriteButton_Click(object sender, RoutedEventArgs e) { case ContentDialogResult.Primary: // Save, then continue the file open - if (!AskFileName(_appFileName) || + if (!AskFileName(string.Empty) || !SaveFile()) { return; diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index 5edab65f9c75..dfce7f88398c 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -834,7 +834,7 @@ private async void HandleDirtyClosing(string title, string content, string prima { case ContentDialogResult.Primary: // Save, then close - if (!AskFileName(_appFileName) || + if (!AskFileName(string.Empty) || !SaveFile()) { return; From 067897d23032c28d7061f6622abe39343c25256c Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 25 Feb 2025 21:43:50 +0100 Subject: [PATCH 13/13] code improvement and fix save as button behavior --- .../RegistryPreviewMainPage.Events.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs index 5f490f205bb4..ab9fd900b21b 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Events.cs @@ -24,7 +24,7 @@ public sealed partial class RegistryPreviewMainPage : Page private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); // Indicator if we loaded/reloaded/saved a file and need to skip TextChanged event one time. - private static bool newFileLoaded; + private static bool editorContentChangedScripted; /// /// Event that is will prevent the app from closing if the "save file" flag is active @@ -147,7 +147,7 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e) { // mute the TextChanged handler to make for clean UI MonacoEditor.TextChanged -= MonacoEditor_TextChanged; - newFileLoaded = true; + editorContentChangedScripted = true; // update file name _appFileName = storageFile.Path; @@ -181,13 +181,19 @@ private void SaveButton_Click(object sender, RoutedEventArgs e) /// private async void SaveAsButton_Click(object sender, RoutedEventArgs e) { - newFileLoaded = true; + // mute the TextChanged handler to make for clean UI + editorContentChangedScripted = true; + MonacoEditor.TextChanged -= MonacoEditor_TextChanged; + if (!AskFileName(_appFileName) || !SaveFile()) { return; } UpdateToolBarAndUI(await OpenRegistryFile(_appFileName)); + + // restore the TextChanged handler + MonacoEditor.TextChanged += MonacoEditor_TextChanged; } /// @@ -196,7 +202,7 @@ private async void SaveAsButton_Click(object sender, RoutedEventArgs e) private async void RefreshButton_Click(object sender, RoutedEventArgs e) { // mute the TextChanged handler to make for clean UI - newFileLoaded = true; + editorContentChangedScripted = true; MonacoEditor.TextChanged -= MonacoEditor_TextChanged; // reload the current Registry file and update the toolbar accordingly. @@ -370,13 +376,13 @@ private void MonacoEditor_TextChanged(object sender, EventArgs e) _dispatcherQueue.TryEnqueue(() => { RefreshRegistryFile(); - if (!newFileLoaded) + if (!editorContentChangedScripted) { saveButton.IsEnabled = true; UpdateUnsavedFileIndicator(true); } - newFileLoaded = false; + editorContentChangedScripted = false; }); } }