From dbae580761051a33f247f5025131e4c176ad099f Mon Sep 17 00:00:00 2001 From: Serafima Date: Thu, 12 Nov 2020 09:38:39 +0300 Subject: [PATCH 01/14] read zone-settings.json --- .../Utils/FancyZonesEditorIO.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index 4e9017bfc8e0..994731350aa2 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -19,6 +19,7 @@ public class FancyZonesEditorIO { // Non-localizable strings: JSON tags private const string AppliedZonesetsJsonTag = "applied-zonesets"; + private const string DevicesJsonTag = "devices"; private const string DeviceIdJsonTag = "device-id"; private const string ActiveZoneSetJsonTag = "active-zoneset"; private const string UuidJsonTag = "uuid"; @@ -325,32 +326,30 @@ public void ParseDeviceInfoData() { JsonElement jsonObject = default(JsonElement); - if (_fileSystem.File.Exists(ActiveZoneSetTmpFile)) + if (_fileSystem.File.Exists(FancyZonesSettingsFile)) { - Stream inputStream = _fileSystem.File.Open(ActiveZoneSetTmpFile, FileMode.Open); + Stream inputStream = _fileSystem.File.Open(FancyZonesSettingsFile, FileMode.Open); jsonObject = JsonDocument.Parse(inputStream, options: default).RootElement; inputStream.Close(); - JsonElement json = jsonObject.GetProperty(AppliedZonesetsJsonTag); + JsonElement json = jsonObject.GetProperty(DevicesJsonTag); + var monitors = App.Overlay.Monitors; - int layoutId = 0; - for (int i = 0; i < json.GetArrayLength() && layoutId < App.Overlay.DesktopsCount; i++) + for (int i = 0; i < json.GetArrayLength(); i++) { var zonesetData = json[i]; string deviceId = zonesetData.GetProperty(DeviceIdJsonTag).GetString(); - string currentLayoutType = zonesetData.GetProperty(ActiveZoneSetJsonTag).GetProperty(TypeJsonTag).GetString(); LayoutType type = JsonTagToLayoutType(currentLayoutType); if (!App.Overlay.SpanZonesAcrossMonitors) { - var monitors = App.Overlay.Monitors; - for (int monitorIndex = 0; monitorIndex < monitors.Count; monitorIndex++) + foreach (Monitor monitor in monitors) { - if (monitors[monitorIndex].Device.Id == deviceId) + if (monitor.Device.Id == deviceId) { - monitors[monitorIndex].Settings = new LayoutSettings + monitor.Settings = new LayoutSettings { ZonesetUuid = zonesetData.GetProperty(ActiveZoneSetJsonTag).GetProperty(UuidJsonTag).GetString(), ShowSpacing = zonesetData.GetProperty(EditorShowSpacingJsonTag).GetBoolean(), From 0d52e7580f039bb400f6488095b41150da105268 Mon Sep 17 00:00:00 2001 From: Serafima Date: Thu, 12 Nov 2020 09:38:58 +0300 Subject: [PATCH 02/14] removed temp file serialization (on editor opening) --- src/modules/fancyzones/lib/FancyZones.cpp | 3 --- src/modules/fancyzones/lib/FancyZonesData.cpp | 5 ----- src/modules/fancyzones/lib/FancyZonesData.h | 1 - 3 files changed, 9 deletions(-) diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index f86302af6008..9298337d4ac7 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -683,9 +683,6 @@ void FancyZones::ToggleEditor() noexcept MB_OK | MB_ICONWARNING); } - const auto& fancyZonesData = FancyZonesDataInstance(); - fancyZonesData.SerializeDeviceInfoToTmpFile(m_currentDesktopId); - SHELLEXECUTEINFO sei{ sizeof(sei) }; sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; sei.lpFile = NonLocalizable::FZEditorExecutablePath; diff --git a/src/modules/fancyzones/lib/FancyZonesData.cpp b/src/modules/fancyzones/lib/FancyZonesData.cpp index 281cb2fa91a3..54aea4a8549d 100644 --- a/src/modules/fancyzones/lib/FancyZonesData.cpp +++ b/src/modules/fancyzones/lib/FancyZonesData.cpp @@ -479,11 +479,6 @@ void FancyZonesData::SetActiveZoneSet(const std::wstring& deviceId, const FancyZ } } -void FancyZonesData::SerializeDeviceInfoToTmpFile(const GUID& currentVirtualDesktop) const -{ - JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, currentVirtualDesktop, activeZoneSetTmpFileName); -} - void FancyZonesData::ParseDataFromTmpFiles() { ParseDeviceInfoFromTmpFile(activeZoneSetTmpFileName); diff --git a/src/modules/fancyzones/lib/FancyZonesData.h b/src/modules/fancyzones/lib/FancyZonesData.h index 74babcd3cdf0..1c89ad881c20 100644 --- a/src/modules/fancyzones/lib/FancyZonesData.h +++ b/src/modules/fancyzones/lib/FancyZonesData.h @@ -72,7 +72,6 @@ class FancyZonesData void SetActiveZoneSet(const std::wstring& deviceId, const FancyZonesDataTypes::ZoneSetData& zoneSet); - void SerializeDeviceInfoToTmpFile(const GUID& currentVirtualDesktop) const; void ParseDataFromTmpFiles(); json::JsonObject GetPersistFancyZonesJSON(); From 12b5dad9240f293b46d4fa5bf2d54efe590d65a4 Mon Sep 17 00:00:00 2001 From: Serafima Date: Fri, 11 Dec 2020 21:41:39 +0300 Subject: [PATCH 03/14] refactoring --- .../editor/FancyZonesEditor/Overlay.cs | 8 +++--- .../Utils/FancyZonesEditorIO.cs | 28 +++++++------------ 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Overlay.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Overlay.cs index 72edf0f0147e..fa1660fc6ea8 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Overlay.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Overlay.cs @@ -29,7 +29,7 @@ public Rect WorkArea return Monitors[CurrentDesktop].Device.WorkAreaRect; } - return default(Rect); + return default; } } @@ -55,7 +55,7 @@ public Window CurrentLayoutWindow return Monitors[CurrentDesktop].Window; } - return default(Window); + return default; } } @@ -131,8 +131,8 @@ public bool SpanZonesAcrossMonitors if (_spanZonesAcrossMonitors) { - Rect workArea = default(Rect); - Rect bounds = default(Rect); + Rect workArea = default; + Rect bounds = default; foreach (Monitor monitor in Monitors) { diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index 994731350aa2..eda3fbca4963 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -645,25 +645,17 @@ private LayoutType JsonTagToLayoutType(string tag) private string LayoutTypeToJsonTag(LayoutType type) { - switch (type) + return type switch { - case LayoutType.Blank: - return BlankJsonTag; - case LayoutType.Focus: - return FocusJsonTag; - case LayoutType.Rows: - return RowsJsonTag; - case LayoutType.Columns: - return ColumnsJsonTag; - case LayoutType.Grid: - return GridJsonTag; - case LayoutType.PriorityGrid: - return PriorityGridJsonTag; - case LayoutType.Custom: - return CustomJsonTag; - } - - return string.Empty; + LayoutType.Blank => BlankJsonTag, + LayoutType.Focus => FocusJsonTag, + LayoutType.Rows => RowsJsonTag, + LayoutType.Columns => ColumnsJsonTag, + LayoutType.Grid => GridJsonTag, + LayoutType.PriorityGrid => PriorityGridJsonTag, + LayoutType.Custom => CustomJsonTag, + _ => string.Empty, + }; } private static string ParsingCmdArgsErrorReport(string args, int count, string targetMonitorName, List monitorData, List monitors) From ea94c036ee4ebd4fbb0dfa3f7581aea5478c4fee Mon Sep 17 00:00:00 2001 From: Serafima Date: Tue, 15 Dec 2020 22:48:12 +0300 Subject: [PATCH 04/14] editor data serialization and deserialization --- .../editor/FancyZonesEditor/App.xaml.cs | 2 +- .../editor/FancyZonesEditor/EditorWindow.cs | 2 +- .../FancyZonesEditor/MainWindow.xaml.cs | 9 +- .../Models/CanvasLayoutModel.cs | 76 +-- .../Models/GridLayoutModel.cs | 62 +-- .../FancyZonesEditor/Models/LayoutModel.cs | 48 +- .../Models/MainWindowSettingsModel.cs | 13 +- .../Utils/FancyZonesEditorIO.cs | 464 ++++++++---------- 8 files changed, 227 insertions(+), 449 deletions(-) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs index 392b3fb800c9..72e79706594d 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs @@ -87,7 +87,7 @@ private void OnStartup(object sender, StartupEventArgs e) _themeManager = new ThemeManager(this); FancyZonesEditorIO.ParseCommandLineArguments(); - FancyZonesEditorIO.ParseDeviceInfoData(); + FancyZonesEditorIO.ParseZoneSettings(); MainWindowSettingsModel settings = ((App)Current).MainWindowSettings; settings.UpdateSelectedLayoutModel(); diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/EditorWindow.cs b/src/modules/fancyzones/editor/FancyZonesEditor/EditorWindow.cs index d49f745c2a46..3d480996cf33 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/EditorWindow.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/EditorWindow.cs @@ -25,7 +25,7 @@ protected void OnSaveApplyTemplate(object sender, RoutedEventArgs e) model.Persist(); } - LayoutModel.SerializeDeletedCustomZoneSets(); + App.FancyZonesEditorIO.SerializeZoneSettings(); _backToLayoutPicker = false; Close(); diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/MainWindow.xaml.cs b/src/modules/fancyzones/editor/FancyZonesEditor/MainWindow.xaml.cs index 9c96fe2201a3..6772cd60b07a 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/MainWindow.xaml.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/MainWindow.xaml.cs @@ -196,7 +196,7 @@ private void Apply() private void OnClosing(object sender, EventArgs e) { - LayoutModel.SerializeDeletedCustomZoneSets(); + App.FancyZonesEditorIO.SerializeZoneSettings(); App.Overlay.CloseLayoutWindow(); App.Current.Shutdown(); } @@ -250,7 +250,6 @@ private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e private void Reset_Click(object sender, RoutedEventArgs e) { var overlay = App.Overlay; - MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings; if (overlay.CurrentDataContext is LayoutModel model) { @@ -258,11 +257,11 @@ private void Reset_Click(object sender, RoutedEventArgs e) model.IsApplied = false; } - overlay.CurrentLayoutSettings.ZonesetUuid = settings.BlankModel.Uuid; + overlay.CurrentLayoutSettings.ZonesetUuid = MainWindowSettingsModel.BlankModel.Uuid; overlay.CurrentLayoutSettings.Type = LayoutType.Blank; - overlay.CurrentDataContext = settings.BlankModel; + overlay.CurrentDataContext = MainWindowSettingsModel.BlankModel; - App.FancyZonesEditorIO.SerializeAppliedLayouts(); + App.FancyZonesEditorIO.SerializeZoneSettings(); if (!overlay.MultiMonitorMode) { diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/CanvasLayoutModel.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/CanvasLayoutModel.cs index 03ac60aaaaa3..f6bc3d061c92 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/CanvasLayoutModel.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/CanvasLayoutModel.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.Text.Json; using System.Windows; namespace FancyZonesEditor.Models @@ -14,7 +13,7 @@ namespace FancyZonesEditor.Models public class CanvasLayoutModel : LayoutModel { // Non-localizable strings - private const string ModelTypeID = "canvas"; + public const string ModelTypeID = "canvas"; public Rect CanvasRect { get; private set; } @@ -83,84 +82,11 @@ public void RestoreTo(CanvasLayoutModel other) } } - private struct Zone - { - public int X { get; set; } - - public int Y { get; set; } - - public int Width { get; set; } - - public int Height { get; set; } - } - - private struct CanvasLayoutInfo - { - public int RefWidth { get; set; } - - public int RefHeight { get; set; } - - public Zone[] Zones { get; set; } - } - - private struct CanvasLayoutJson - { - public string Uuid { get; set; } - - public string Name { get; set; } - - public string Type { get; set; } - - public CanvasLayoutInfo Info { get; set; } - } - // PersistData // Implements the LayoutModel.PersistData abstract method protected override void PersistData() { AddCustomLayout(this); - - var canvasRect = CanvasRect; - if (canvasRect.Width == 0 || canvasRect.Height == 0) - { - canvasRect = App.Overlay.WorkArea; - } - - CanvasLayoutInfo layoutInfo = new CanvasLayoutInfo - { - RefWidth = (int)canvasRect.Width, - RefHeight = (int)canvasRect.Height, - Zones = new Zone[Zones.Count], - }; - - for (int i = 0; i < Zones.Count; ++i) - { - Zone zone = new Zone - { - X = Zones[i].X, - Y = Zones[i].Y, - Width = Zones[i].Width, - Height = Zones[i].Height, - }; - - layoutInfo.Zones[i] = zone; - } - - CanvasLayoutJson jsonObj = new CanvasLayoutJson - { - Uuid = Uuid, - Name = Name, - Type = ModelTypeID, - Info = layoutInfo, - }; - JsonSerializerOptions options = new JsonSerializerOptions - { - PropertyNamingPolicy = new DashCaseNamingPolicy(), - }; - - string jsonString = JsonSerializer.Serialize(jsonObj, options); - AddCustomLayoutJson(JsonSerializer.Deserialize(jsonString)); - SerializeCreatedCustomZonesets(); } } } diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/GridLayoutModel.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/GridLayoutModel.cs index 1dbc391e13d8..ed2ff44130a5 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/GridLayoutModel.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/GridLayoutModel.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Generic; -using System.Text.Json; -using System.Windows; namespace FancyZonesEditor.Models { @@ -14,7 +12,7 @@ namespace FancyZonesEditor.Models public class GridLayoutModel : LayoutModel { // Non-localizable strings - private const string ModelTypeID = "grid"; + public const string ModelTypeID = "grid"; // Rows - number of rows in the Grid public int Rows @@ -173,69 +171,11 @@ public void RestoreTo(GridLayoutModel layout) layout.ColumnPercents = colPercents; } - private struct GridLayoutInfo - { - public int Rows { get; set; } - - public int Columns { get; set; } - - public List RowsPercentage { get; set; } - - public List ColumnsPercentage { get; set; } - - public int[][] CellChildMap { get; set; } - } - - private struct GridLayoutJson - { - public string Uuid { get; set; } - - public string Name { get; set; } - - public string Type { get; set; } - - public GridLayoutInfo Info { get; set; } - } - // PersistData // Implements the LayoutModel.PersistData abstract method protected override void PersistData() { AddCustomLayout(this); - - GridLayoutInfo layoutInfo = new GridLayoutInfo - { - Rows = Rows, - Columns = Columns, - RowsPercentage = RowPercents, - ColumnsPercentage = ColumnPercents, - CellChildMap = new int[Rows][], - }; - - for (int row = 0; row < Rows; row++) - { - layoutInfo.CellChildMap[row] = new int[Columns]; - for (int col = 0; col < Columns; col++) - { - layoutInfo.CellChildMap[row][col] = CellChildMap[row, col]; - } - } - - GridLayoutJson jsonObj = new GridLayoutJson - { - Uuid = Uuid, - Name = Name, - Type = ModelTypeID, - Info = layoutInfo, - }; - JsonSerializerOptions options = new JsonSerializerOptions - { - PropertyNamingPolicy = new DashCaseNamingPolicy(), - }; - - string jsonString = JsonSerializer.Serialize(jsonObj, options); - AddCustomLayoutJson(JsonSerializer.Deserialize(jsonString)); - SerializeCreatedCustomZonesets(); } } } diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutModel.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutModel.cs index 61d3ac76bdae..4ace86920b15 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutModel.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutModel.cs @@ -3,11 +3,8 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; -using System.Text.Json; namespace FancyZonesEditor.Models { @@ -134,11 +131,11 @@ protected virtual void FirePropertyChanged([CallerMemberName] string propertyNam // Removes this Layout from the registry and the loaded CustomModels list public void Delete() { - int i = _customModels.IndexOf(this); + var customModels = MainWindowSettingsModel.CustomModels; + int i = customModels.IndexOf(this); if (i != -1) { - _customModels.RemoveAt(i); - _deletedCustomModels.Add(Guid.ToString().ToUpper()); + customModels.RemoveAt(i); } } @@ -146,49 +143,24 @@ public void Delete() public void AddCustomLayout(LayoutModel model) { bool updated = false; - for (int i = 0; i < _customModels.Count && !updated; i++) + var customModels = MainWindowSettingsModel.CustomModels; + for (int i = 0; i < customModels.Count && !updated; i++) { - if (_customModels[i].Uuid == model.Uuid) + if (customModels[i].Uuid == model.Uuid) { - _customModels[i] = model; + customModels[i] = model; updated = true; } } if (!updated) { - _customModels.Add(model); + customModels.Add(model); } - } - - // Add custom layouts json data that would be serialized to a temp file - public void AddCustomLayoutJson(JsonElement json) - { - _createdCustomLayouts.Add(json); - } - - public static void SerializeDeletedCustomZoneSets() - { - App.FancyZonesEditorIO.SerializeDeletedCustomZoneSets(_deletedCustomModels); - } - - public static void SerializeCreatedCustomZonesets() - { - App.FancyZonesEditorIO.SerializeCreatedCustomZonesets(_createdCustomLayouts); - } - // Loads all the custom Layouts from tmp file passed by FancyZonesLib - public static ObservableCollection LoadCustomModels() - { - _customModels = new ObservableCollection(); - App.FancyZonesEditorIO.ParseLayouts(ref _customModels, ref _deletedCustomModels); - return _customModels; + App.FancyZonesEditorIO.SerializeZoneSettings(); } - private static ObservableCollection _customModels; - private static List _deletedCustomModels = new List(); - private static List _createdCustomLayouts = new List(); - // Callbacks that the base LayoutModel makes to derived types protected abstract void PersistData(); @@ -211,7 +183,7 @@ public void Apply() App.Overlay.CurrentLayoutSettings.Type = Type; // update temp file - App.FancyZonesEditorIO.SerializeAppliedLayouts(); + App.FancyZonesEditorIO.SerializeZoneSettings(); } } } diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/MainWindowSettingsModel.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/MainWindowSettingsModel.cs index d628367688bd..65d3797db10a 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/MainWindowSettingsModel.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/MainWindowSettingsModel.cs @@ -344,27 +344,20 @@ public static ObservableCollection CustomModels { get { - if (_customModels == null) - { - _customModels = LayoutModel.LoadCustomModels(); - } - return _customModels; } } - private static ObservableCollection _customModels; + private static ObservableCollection _customModels = new ObservableCollection(); - public CanvasLayoutModel BlankModel + public static CanvasLayoutModel BlankModel { get { - return _blankModel; + return _blankCustomModel; } } - private CanvasLayoutModel _blankModel = new CanvasLayoutModel(string.Empty, LayoutType.Blank); - public static bool IsPredefinedLayout(LayoutModel model) { return model.Type != LayoutType.Custom; diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index eda3fbca4963..3445acf7eb85 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -4,10 +4,8 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.IO; using System.IO.Abstractions; -using System.Linq; using System.Text; using System.Text.Json; using System.Windows; @@ -18,17 +16,6 @@ namespace FancyZonesEditor.Utils public class FancyZonesEditorIO { // Non-localizable strings: JSON tags - private const string AppliedZonesetsJsonTag = "applied-zonesets"; - private const string DevicesJsonTag = "devices"; - private const string DeviceIdJsonTag = "device-id"; - private const string ActiveZoneSetJsonTag = "active-zoneset"; - private const string UuidJsonTag = "uuid"; - private const string TypeJsonTag = "type"; - private const string EditorShowSpacingJsonTag = "editor-show-spacing"; - private const string EditorSpacingJsonTag = "editor-spacing"; - private const string EditorZoneCountJsonTag = "editor-zone-count"; - private const string EditorSensitivityRadiusJsonTag = "editor-sensitivity-radius"; - private const string BlankJsonTag = "blank"; private const string FocusJsonTag = "focus"; private const string ColumnsJsonTag = "columns"; @@ -37,43 +24,19 @@ public class FancyZonesEditorIO private const string PriorityGridJsonTag = "priority-grid"; private const string CustomJsonTag = "custom"; - private const string NameJsonTag = "name"; - private const string CustomZoneSetsJsonTag = "custom-zone-sets"; - private const string InfoJsonTag = "info"; - private const string RowsPercentageJsonTag = "rows-percentage"; - private const string ColumnsPercentageJsonTag = "columns-percentage"; - private const string CellChildMapJsonTag = "cell-child-map"; - private const string ZonesJsonTag = "zones"; - private const string CanvasJsonTag = "canvas"; - private const string RefWidthJsonTag = "ref-width"; - private const string RefHeightJsonTag = "ref-height"; - private const string XJsonTag = "X"; - private const string YJsonTag = "Y"; - private const string WidthJsonTag = "width"; - private const string HeightJsonTag = "height"; - // Non-localizable strings: Files private const string ZonesSettingsFile = "\\Microsoft\\PowerToys\\FancyZones\\zones-settings.json"; - private const string ActiveZoneSetsTmpFileName = "FancyZonesActiveZoneSets.json"; - private const string AppliedZoneSetsTmpFileName = "FancyZonesAppliedZoneSets.json"; - private const string DeletedCustomZoneSetsTmpFileName = "FancyZonesDeletedCustomZoneSets.json"; // Non-localizable string: Multi-monitor id private const string MultiMonitorId = "FancyZones#MultiMonitorDevice"; private readonly IFileSystem _fileSystem = new FileSystem(); - private JsonSerializerOptions _options = new JsonSerializerOptions + private readonly JsonSerializerOptions _options = new JsonSerializerOptions { PropertyNamingPolicy = new DashCaseNamingPolicy(), }; - public string ActiveZoneSetTmpFile { get; private set; } - - public string AppliedZoneSetTmpFile { get; private set; } - - public string DeletedCustomZoneSetsTmpFile { get; private set; } - public string FancyZonesSettingsFile { get; private set; } private enum CmdArgs @@ -123,7 +86,7 @@ private struct ActiveZoneSetWrapper public string Type { get; set; } } - private struct AppliedZoneSet + private struct DeviceWrapper { public string DeviceId { get; set; } @@ -138,29 +101,81 @@ private struct AppliedZoneSet public int EditorSensitivityRadius { get; set; } } - private struct AppliedZonesetsToDesktops + private struct CanvasZoneWrapper { - public List AppliedZonesets { get; set; } + public int X { get; set; } + + public int Y { get; set; } + + public int Width { get; set; } + + public int Height { get; set; } } - private struct DeletedCustomZoneSetsWrapper + private struct CanvasInfoWrapper { - public List DeletedCustomZoneSets { get; set; } + public int RefWidth { get; set; } + + public int RefHeight { get; set; } + + public List Zones { get; set; } } - private struct CreatedCustomZoneSetsWrapper + private struct GridInfoWrapper { - public List CreatedCustomZoneSets { get; set; } + public int Rows { get; set; } + + public int Columns { get; set; } + + public List RowsPercentage { get; set; } + + public List ColumnsPercentage { get; set; } + + public int[][] CellChildMap { get; set; } } - public FancyZonesEditorIO() + private struct CustomLayoutWrapper { - string tmpDirPath = _fileSystem.Path.GetTempPath(); + public string Uuid { get; set; } + + public string Name { get; set; } - ActiveZoneSetTmpFile = tmpDirPath + ActiveZoneSetsTmpFileName; - AppliedZoneSetTmpFile = tmpDirPath + AppliedZoneSetsTmpFileName; - DeletedCustomZoneSetsTmpFile = tmpDirPath + DeletedCustomZoneSetsTmpFileName; + public string Type { get; set; } + + public JsonElement Info { get; set; } + } + private struct CustomCanvasLayoutWrapper + { + public string Uuid { get; set; } + + public string Name { get; set; } + + public string Type { get; set; } + + public CanvasInfoWrapper Info { get; set; } + } + + private struct CustomGridLayoutWrapper + { + public string Uuid { get; set; } + + public string Name { get; set; } + + public string Type { get; set; } + + public GridInfoWrapper Info { get; set; } + } + + private struct ZoneSettingsWrapper + { + public List Devices { get; set; } + + public List CustomZoneSets { get; set; } + } + + public FancyZonesEditorIO() + { var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); FancyZonesSettingsFile = localAppDataDir + ZonesSettingsFile; } @@ -320,228 +335,113 @@ public static void ParseCommandLineArguments() } } - public void ParseDeviceInfoData() + public void ParseZoneSettings() { try { - JsonElement jsonObject = default(JsonElement); - if (_fileSystem.File.Exists(FancyZonesSettingsFile)) { Stream inputStream = _fileSystem.File.Open(FancyZonesSettingsFile, FileMode.Open); - jsonObject = JsonDocument.Parse(inputStream, options: default).RootElement; + StreamReader reader = new StreamReader(inputStream); + string data = reader.ReadToEnd(); inputStream.Close(); - JsonElement json = jsonObject.GetProperty(DevicesJsonTag); - var monitors = App.Overlay.Monitors; + var zoneSettings = JsonSerializer.Deserialize(data, _options); - for (int i = 0; i < json.GetArrayLength(); i++) + // Set devices + var monitors = App.Overlay.Monitors; + foreach (var device in zoneSettings.Devices) { - var zonesetData = json[i]; - - string deviceId = zonesetData.GetProperty(DeviceIdJsonTag).GetString(); - string currentLayoutType = zonesetData.GetProperty(ActiveZoneSetJsonTag).GetProperty(TypeJsonTag).GetString(); - LayoutType type = JsonTagToLayoutType(currentLayoutType); + var settings = new LayoutSettings + { + ZonesetUuid = device.ActiveZoneset.Uuid, + ShowSpacing = device.EditorShowSpacing, + Spacing = device.EditorSpacing, + Type = JsonTagToLayoutType(device.ActiveZoneset.Type), + ZoneCount = device.EditorZoneCount, + SensitivityRadius = device.EditorSensitivityRadius, + }; if (!App.Overlay.SpanZonesAcrossMonitors) { foreach (Monitor monitor in monitors) { - if (monitor.Device.Id == deviceId) + if (monitor.Device.Id == device.DeviceId) { - monitor.Settings = new LayoutSettings - { - ZonesetUuid = zonesetData.GetProperty(ActiveZoneSetJsonTag).GetProperty(UuidJsonTag).GetString(), - ShowSpacing = zonesetData.GetProperty(EditorShowSpacingJsonTag).GetBoolean(), - Spacing = zonesetData.GetProperty(EditorSpacingJsonTag).GetInt32(), - Type = type, - ZoneCount = zonesetData.GetProperty(EditorZoneCountJsonTag).GetInt32(), - SensitivityRadius = zonesetData.GetProperty(EditorSensitivityRadiusJsonTag).GetInt32(), - }; - + monitor.Settings = settings; break; } } } else { - bool isLayoutMultiMonitor = deviceId.StartsWith(MultiMonitorId); + bool isLayoutMultiMonitor = device.DeviceId.StartsWith(MultiMonitorId); if (isLayoutMultiMonitor) { // one zoneset for all desktops - App.Overlay.Monitors[App.Overlay.CurrentDesktop].Settings = new LayoutSettings - { - ZonesetUuid = zonesetData.GetProperty(ActiveZoneSetJsonTag).GetProperty(UuidJsonTag).GetString(), - ShowSpacing = zonesetData.GetProperty(EditorShowSpacingJsonTag).GetBoolean(), - Spacing = zonesetData.GetProperty(EditorSpacingJsonTag).GetInt32(), - Type = type, - ZoneCount = zonesetData.GetProperty(EditorZoneCountJsonTag).GetInt32(), - SensitivityRadius = zonesetData.GetProperty(EditorSensitivityRadiusJsonTag).GetInt32(), - }; - - App.Overlay.Monitors[App.Overlay.CurrentDesktop].Device.Id = deviceId; - + App.Overlay.Monitors[App.Overlay.CurrentDesktop].Settings = settings; + App.Overlay.Monitors[App.Overlay.CurrentDesktop].Device.Id = device.DeviceId; break; } } } - } - } - catch (Exception ex) - { - App.ShowExceptionMessageBox(Properties.Resources.Error_Parsing_Device_Info, ex); - } - } - public void ParseLayouts(ref ObservableCollection custom, ref List deleted) - { - try - { - Stream inputStream = _fileSystem.File.Open(FancyZonesSettingsFile, FileMode.Open); - JsonDocument jsonObject = JsonDocument.Parse(inputStream, options: default); - JsonElement.ArrayEnumerator customZoneSetsEnumerator = jsonObject.RootElement.GetProperty(CustomZoneSetsJsonTag).EnumerateArray(); - - while (customZoneSetsEnumerator.MoveNext()) - { - var current = customZoneSetsEnumerator.Current; - string name = current.GetProperty(NameJsonTag).GetString(); - string type = current.GetProperty(TypeJsonTag).GetString(); - string uuid = current.GetProperty(UuidJsonTag).GetString(); - var info = current.GetProperty(InfoJsonTag); - - if (type.Equals(GridJsonTag, StringComparison.OrdinalIgnoreCase)) + // Set layouts + MainWindowSettingsModel.CustomModels.Clear(); + MainWindowSettingsModel.CustomModels.Add(MainWindowSettingsModel.BlankModel); + foreach (var zoneSet in zoneSettings.CustomZoneSets) { - bool error = false; - - int rows = info.GetProperty(RowsJsonTag).GetInt32(); - int columns = info.GetProperty(ColumnsJsonTag).GetInt32(); - - List rowsPercentage = new List(rows); - JsonElement.ArrayEnumerator rowsPercentageEnumerator = info.GetProperty(RowsPercentageJsonTag).EnumerateArray(); - - List columnsPercentage = new List(columns); - JsonElement.ArrayEnumerator columnsPercentageEnumerator = info.GetProperty(ColumnsPercentageJsonTag).EnumerateArray(); - - if (rows <= 0 || columns <= 0 || rowsPercentageEnumerator.Count() != rows || columnsPercentageEnumerator.Count() != columns) + LayoutModel layout; + if (zoneSet.Type == CanvasLayoutModel.ModelTypeID) { - error = true; - } + var info = JsonSerializer.Deserialize(zoneSet.Info.GetRawText(), _options); - while (!error && rowsPercentageEnumerator.MoveNext()) - { - int percentage = rowsPercentageEnumerator.Current.GetInt32(); - if (percentage <= 0) + var zones = new List(); + foreach (var zone in info.Zones) { - error = true; - break; + zones.Add(new Int32Rect { X = (int)zone.X, Y = (int)zone.Y, Width = (int)zone.Width, Height = (int)zone.Height }); } - rowsPercentage.Add(percentage); + layout = new CanvasLayoutModel(zoneSet.Uuid, zoneSet.Name, LayoutType.Custom, zones, info.RefWidth, info.RefHeight); } - - while (!error && columnsPercentageEnumerator.MoveNext()) + else if (zoneSet.Type == GridLayoutModel.ModelTypeID) { - int percentage = columnsPercentageEnumerator.Current.GetInt32(); - if (percentage <= 0) - { - error = true; - break; - } - - columnsPercentage.Add(percentage); - } - - int i = 0; - JsonElement.ArrayEnumerator cellChildMapRows = info.GetProperty(CellChildMapJsonTag).EnumerateArray(); - int[,] cellChildMap = new int[rows, columns]; - - if (cellChildMapRows.Count() != rows) - { - error = true; - } + var info = JsonSerializer.Deserialize(zoneSet.Info.GetRawText(), _options); - while (!error && cellChildMapRows.MoveNext()) - { - int j = 0; - JsonElement.ArrayEnumerator cellChildMapRowElems = cellChildMapRows.Current.EnumerateArray(); - if (cellChildMapRowElems.Count() != columns) + var cells = new int[info.Rows, info.Columns]; + for (int row = 0; row < info.Rows; row++) { - error = true; - break; - } - - while (cellChildMapRowElems.MoveNext()) - { - cellChildMap[i, j++] = cellChildMapRowElems.Current.GetInt32(); - } - - i++; - } - - if (error) - { - App.ShowExceptionMessageBox(string.Format(Properties.Resources.Error_Layout_Malformed_Data, name)); - deleted.Add(Guid.Parse(uuid).ToString().ToUpperInvariant()); - continue; - } - - custom.Add(new GridLayoutModel(uuid, name, LayoutType.Custom, rows, columns, rowsPercentage, columnsPercentage, cellChildMap)); - } - else if (type.Equals(CanvasJsonTag, StringComparison.OrdinalIgnoreCase)) - { - int workAreaWidth = info.GetProperty(RefWidthJsonTag).GetInt32(); - int workAreaHeight = info.GetProperty(RefHeightJsonTag).GetInt32(); - - JsonElement.ArrayEnumerator zonesEnumerator = info.GetProperty(ZonesJsonTag).EnumerateArray(); - IList zones = new List(); - - bool error = false; - - if (workAreaWidth <= 0 || workAreaHeight <= 0) - { - error = true; - } - - while (!error && zonesEnumerator.MoveNext()) - { - int x = zonesEnumerator.Current.GetProperty(XJsonTag).GetInt32(); - int y = zonesEnumerator.Current.GetProperty(YJsonTag).GetInt32(); - int width = zonesEnumerator.Current.GetProperty(WidthJsonTag).GetInt32(); - int height = zonesEnumerator.Current.GetProperty(HeightJsonTag).GetInt32(); - - if (width <= 0 || height <= 0) - { - error = true; - break; + for (int column = 0; column < info.Columns; column++) + { + cells[row, column] = info.CellChildMap[row][column]; + } } - zones.Add(new Int32Rect(x, y, width, height)); + layout = new GridLayoutModel(zoneSet.Uuid, zoneSet.Name, LayoutType.Custom, info.Rows, info.Columns, info.RowsPercentage, info.ColumnsPercentage, cells); } - - if (error) + else { - App.ShowExceptionMessageBox(string.Format(Properties.Resources.Error_Layout_Malformed_Data, name)); - deleted.Add(Guid.Parse(uuid).ToString().ToUpperInvariant()); + // Error continue; } - custom.Add(new CanvasLayoutModel(uuid, name, LayoutType.Custom, zones, workAreaWidth, workAreaHeight)); + MainWindowSettingsModel.CustomModels.Add(layout); } } - - inputStream.Close(); } catch (Exception ex) { - App.ShowExceptionMessageBox(Properties.Resources.Error_Loading_Custom_Layouts, ex); + App.ShowExceptionMessageBox(Properties.Resources.Error_Parsing_Device_Info, ex); } } - public void SerializeAppliedLayouts() + public void SerializeZoneSettings() { - AppliedZonesetsToDesktops applied = new AppliedZonesetsToDesktops { }; - applied.AppliedZonesets = new List(); + ZoneSettingsWrapper zoneSettings = new ZoneSettingsWrapper { }; + zoneSettings.Devices = new List(); + zoneSettings.CustomZoneSets = new List(); + // Serialize devices foreach (var monitor in App.Overlay.Monitors) { LayoutSettings zoneset = monitor.Settings; @@ -550,17 +450,14 @@ public void SerializeAppliedLayouts() continue; } - ActiveZoneSetWrapper activeZoneSet = new ActiveZoneSetWrapper - { - Uuid = zoneset.ZonesetUuid, - }; - - activeZoneSet.Type = LayoutTypeToJsonTag(zoneset.Type); - - applied.AppliedZonesets.Add(new AppliedZoneSet + zoneSettings.Devices.Add(new DeviceWrapper { DeviceId = monitor.Device.Id, - ActiveZoneset = activeZoneSet, + ActiveZoneset = new ActiveZoneSetWrapper + { + Uuid = zoneset.ZonesetUuid, + Type = LayoutTypeToJsonTag(zoneset.Type), + }, EditorShowSpacing = zoneset.ShowSpacing, EditorSpacing = zoneset.Spacing, EditorZoneCount = zoneset.ZoneCount, @@ -568,50 +465,101 @@ public void SerializeAppliedLayouts() }); } - try + // Serialize custom zonesets + foreach (LayoutModel layout in MainWindowSettingsModel.CustomModels) { - string jsonString = JsonSerializer.Serialize(applied, _options); - _fileSystem.File.WriteAllText(ActiveZoneSetTmpFile, jsonString); - } - catch (Exception ex) - { - App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex); - } - } + if (layout.Type == LayoutType.Blank) + { + continue; + } - public void SerializeDeletedCustomZoneSets(List models) - { - DeletedCustomZoneSetsWrapper deletedLayouts = new DeletedCustomZoneSetsWrapper - { - DeletedCustomZoneSets = models, - }; + JsonElement info; + string type; - try - { - string jsonString = JsonSerializer.Serialize(deletedLayouts, _options); - _fileSystem.File.WriteAllText(DeletedCustomZoneSetsTmpFile, jsonString); - } - catch (Exception ex) - { - App.ShowExceptionMessageBox(Properties.Resources.Error_Serializing_Deleted_Layouts, ex); - } - } + if (layout is CanvasLayoutModel) + { + type = CanvasLayoutModel.ModelTypeID; + var canvasLayout = layout as CanvasLayoutModel; - public void SerializeCreatedCustomZonesets(List models) - { - CreatedCustomZoneSetsWrapper layouts = new CreatedCustomZoneSetsWrapper - { - CreatedCustomZoneSets = models, - }; + var canvasRect = canvasLayout.CanvasRect; + if (canvasRect.Width == 0 || canvasRect.Height == 0) + { + canvasRect = App.Overlay.WorkArea; + } + + var wrapper = new CanvasInfoWrapper + { + RefWidth = (int)canvasRect.Width, + RefHeight = (int)canvasRect.Height, + Zones = new List(), + }; + + foreach (var zone in canvasLayout.Zones) + { + wrapper.Zones.Add(new CanvasZoneWrapper + { + X = zone.X, + Y = zone.Y, + Width = zone.Width, + Height = zone.Height, + }); + } + + string json = JsonSerializer.Serialize(wrapper, _options); + info = JsonSerializer.Deserialize(json); + } + else if (layout is GridLayoutModel) + { + type = GridLayoutModel.ModelTypeID; + var gridLayout = layout as GridLayoutModel; + + var cells = new int[gridLayout.Rows][]; + for (int row = 0; row < gridLayout.Rows; row++) + { + cells[row] = new int[gridLayout.Columns]; + for (int column = 0; column < gridLayout.Columns; column++) + { + cells[row][column] = gridLayout.CellChildMap[row, column]; + } + } + + var wrapper = new GridInfoWrapper + { + Rows = gridLayout.Rows, + Columns = gridLayout.Columns, + RowsPercentage = gridLayout.RowPercents, + ColumnsPercentage = gridLayout.ColumnPercents, + CellChildMap = cells, + }; + + string json = JsonSerializer.Serialize(wrapper, _options); + info = JsonSerializer.Deserialize(json); + } + else + { + // Error + continue; + } + + CustomLayoutWrapper customLayout = new CustomLayoutWrapper + { + Uuid = layout.Uuid, + Name = layout.Name, + Type = type, + Info = info, + }; + + zoneSettings.CustomZoneSets.Add(customLayout); + } try { - string jsonString = JsonSerializer.Serialize(layouts, _options); - _fileSystem.File.WriteAllText(AppliedZoneSetTmpFile, jsonString); + string jsonString = JsonSerializer.Serialize(zoneSettings, _options); + _fileSystem.File.WriteAllText(FancyZonesSettingsFile, jsonString); } catch (Exception ex) { - App.ShowExceptionMessageBox(Properties.Resources.Error_Persisting_Custom_Layout, ex); + App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex); } } From dc75b4871811fafd1e350da44862ee072ecbfd00 Mon Sep 17 00:00:00 2001 From: Serafima Date: Sat, 12 Dec 2020 19:36:15 +0300 Subject: [PATCH 05/14] load data from zones-settings.json --- src/modules/fancyzones/lib/FancyZones.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index 9298337d4ac7..57c4acd3dbb2 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -1294,7 +1294,7 @@ bool FancyZones::IsSplashScreen(HWND window) void FancyZones::OnEditorExitEvent() noexcept { // Collect information about changes in zone layout after editor exited. - FancyZonesDataInstance().ParseDataFromTmpFiles(); + FancyZonesDataInstance().LoadFancyZonesData(); for (auto workArea : m_workAreaHandler.GetAllWorkAreas()) { From b4fd8cde58b81aa5c63d6799adf1b6f74ab25a61 Mon Sep 17 00:00:00 2001 From: Serafima Date: Tue, 15 Dec 2020 22:49:33 +0300 Subject: [PATCH 06/14] removed temp files related code --- src/modules/fancyzones/lib/FancyZonesData.cpp | 51 ------ src/modules/fancyzones/lib/FancyZonesData.h | 10 -- src/modules/fancyzones/lib/JsonHelpers.cpp | 152 ------------------ src/modules/fancyzones/lib/JsonHelpers.h | 17 -- 4 files changed, 230 deletions(-) diff --git a/src/modules/fancyzones/lib/FancyZonesData.cpp b/src/modules/fancyzones/lib/FancyZonesData.cpp index 54aea4a8549d..df7ec124634c 100644 --- a/src/modules/fancyzones/lib/FancyZonesData.cpp +++ b/src/modules/fancyzones/lib/FancyZonesData.cpp @@ -26,10 +26,6 @@ namespace NonLocalizable const wchar_t FancyZonesAppZoneHistoryFile[] = L"app-zone-history.json"; const wchar_t DefaultGuid[] = L"{00000000-0000-0000-0000-000000000000}"; const wchar_t RegistryPath[] = L"Software\\SuperFancyZones"; - - const wchar_t ActiveZoneSetsTmpFileName[] = L"FancyZonesActiveZoneSets.json"; - const wchar_t AppliedZoneSetsTmpFileName[] = L"FancyZonesAppliedZoneSets.json"; - const wchar_t DeletedCustomZoneSetsTmpFileName[] = L"FancyZonesDeletedCustomZoneSets.json"; } namespace @@ -151,10 +147,6 @@ FancyZonesData::FancyZonesData() zonesSettingsFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesDataFile); appZoneHistoryFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesAppZoneHistoryFile); - - activeZoneSetTmpFileName = GetTempDirPath() + NonLocalizable::ActiveZoneSetsTmpFileName; - appliedZoneSetTmpFileName = GetTempDirPath() + NonLocalizable::AppliedZoneSetsTmpFileName; - deletedCustomZoneSetsTmpFileName = GetTempDirPath() + NonLocalizable::DeletedCustomZoneSetsTmpFileName; } std::optional FancyZonesData::FindDeviceInfo(const std::wstring& zoneWindowId) const @@ -479,49 +471,6 @@ void FancyZonesData::SetActiveZoneSet(const std::wstring& deviceId, const FancyZ } } -void FancyZonesData::ParseDataFromTmpFiles() -{ - ParseDeviceInfoFromTmpFile(activeZoneSetTmpFileName); - ParseDeletedCustomZoneSetsFromTmpFile(deletedCustomZoneSetsTmpFileName); - ParseCustomZoneSetsFromTmpFile(appliedZoneSetTmpFileName); - SaveFancyZonesData(); -} - -void FancyZonesData::ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath) -{ - std::scoped_lock lock{ dataLock }; - const auto& appliedZonesets = JSONHelpers::ParseDeviceInfoFromTmpFile(tmpFilePath); - - if (appliedZonesets) - { - for (const auto& zoneset : *appliedZonesets) - { - deviceInfoMap[zoneset.first] = std::move(zoneset.second); - } - } -} - -void FancyZonesData::ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath) -{ - std::scoped_lock lock{ dataLock }; - const auto& customZoneSets = JSONHelpers::ParseCustomZoneSetsFromTmpFile(tmpFilePath); - - for (const auto& zoneSet : customZoneSets) - { - customZoneSetsMap[zoneSet.uuid] = zoneSet.data; - } -} - -void FancyZonesData::ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath) -{ - std::scoped_lock lock{ dataLock }; - const auto& deletedCustomZoneSets = JSONHelpers::ParseDeletedCustomZoneSetsFromTmpFile(tmpFilePath); - for (const auto& zoneSet : deletedCustomZoneSets) - { - customZoneSetsMap.erase(zoneSet); - } -} - json::JsonObject FancyZonesData::GetPersistFancyZonesJSON() { return JSONHelpers::GetPersistFancyZonesJSON(zonesSettingsFileName, appZoneHistoryFileName); diff --git a/src/modules/fancyzones/lib/FancyZonesData.h b/src/modules/fancyzones/lib/FancyZonesData.h index 1c89ad881c20..7d770631d7c1 100644 --- a/src/modules/fancyzones/lib/FancyZonesData.h +++ b/src/modules/fancyzones/lib/FancyZonesData.h @@ -72,8 +72,6 @@ class FancyZonesData void SetActiveZoneSet(const std::wstring& deviceId, const FancyZonesDataTypes::ZoneSetData& zoneSet); - void ParseDataFromTmpFiles(); - json::JsonObject GetPersistFancyZonesJSON(); void LoadFancyZonesData(); @@ -112,10 +110,6 @@ class FancyZonesData appZoneHistoryFileName = result + L"\\" + std::wstring(L"app-zone-history.json"); } #endif - void ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath); - void ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath); - void ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath); - void RemoveDesktopAppZoneHistory(const std::wstring& desktopId); // Maps app path to app's zone history data @@ -128,10 +122,6 @@ class FancyZonesData std::wstring zonesSettingsFileName; std::wstring appZoneHistoryFileName; - std::wstring activeZoneSetTmpFileName; - std::wstring appliedZoneSetTmpFileName; - std::wstring deletedCustomZoneSetsTmpFileName; - mutable std::recursive_mutex dataLock; }; diff --git a/src/modules/fancyzones/lib/JsonHelpers.cpp b/src/modules/fancyzones/lib/JsonHelpers.cpp index 03ba0297ee75..d19a9124826d 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.cpp +++ b/src/modules/fancyzones/lib/JsonHelpers.cpp @@ -15,16 +15,13 @@ namespace NonLocalizable { const wchar_t ActiveZoneSetStr[] = L"active-zoneset"; - const wchar_t AppliedZonesets[] = L"applied-zonesets"; const wchar_t AppPathStr[] = L"app-path"; const wchar_t AppZoneHistoryStr[] = L"app-zone-history"; const wchar_t CanvasStr[] = L"canvas"; const wchar_t CellChildMapStr[] = L"cell-child-map"; const wchar_t ColumnsPercentageStr[] = L"columns-percentage"; const wchar_t ColumnsStr[] = L"columns"; - const wchar_t CreatedCustomZoneSets[] = L"created-custom-zone-sets"; const wchar_t CustomZoneSetsStr[] = L"custom-zone-sets"; - const wchar_t DeletedCustomZoneSetsStr[] = L"deleted-custom-zone-sets"; const wchar_t DeviceIdStr[] = L"device-id"; const wchar_t DevicesStr[] = L"devices"; const wchar_t EditorShowSpacingStr[] = L"editor-show-spacing"; @@ -447,64 +444,6 @@ namespace JSONHelpers } } - json::JsonObject AppliedZonesetsJSON::ToJson(const TDeviceInfoMap& deviceInfoMap) - { - json::JsonObject result{}; - - json::JsonArray array; - for (const auto& info : deviceInfoMap) - { - JSONHelpers::DeviceInfoJSON deviceInfoJson{ info.first, info.second }; - array.Append(JSONHelpers::DeviceInfoJSON::ToJson(deviceInfoJson)); - } - - result.SetNamedValue(NonLocalizable::AppliedZonesets, array); - return result; - } - - json::JsonObject AppliedZonesetsJSON::ToJson(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop) - { - json::JsonObject result{}; - - json::JsonArray array; - for (const auto& info : deviceInfoMap) - { - std::optional id = FancyZonesUtils::ParseDeviceId(info.first); - if (id.has_value() && id->virtualDesktopId == currentVirtualDesktop) - { - JSONHelpers::DeviceInfoJSON deviceInfoJson{ info.first, info.second }; - array.Append(JSONHelpers::DeviceInfoJSON::ToJson(deviceInfoJson)); - } - } - - result.SetNamedValue(NonLocalizable::AppliedZonesets, array); - return result; - } - - std::optional AppliedZonesetsJSON::FromJson(const json::JsonObject& json) - { - try - { - std::unordered_map appliedZonesets; - - auto zonesets = json.GetNamedArray(NonLocalizable::AppliedZonesets); - for (const auto& zoneset : zonesets) - { - std::optional device = DeviceInfoJSON::FromJson(zoneset.GetObjectW()); - if (device.has_value()) - { - appliedZonesets.insert(std::make_pair(device->deviceId, device->data)); - } - } - - return appliedZonesets; - } - catch (const winrt::hresult_error&) - { - return std::nullopt; - } - } - json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName) { auto result = json::from_file(zonesSettingsFileName); @@ -659,95 +598,4 @@ namespace JSONHelpers return customZoneSetsJSON; } - - void SerializeDeviceInfoToTmpFile(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop, std::wstring_view tmpFilePath) - { - json::to_file(tmpFilePath, JSONHelpers::AppliedZonesetsJSON::ToJson(deviceInfoMap, currentVirtualDesktop)); - } - - void SerializeCustomZoneSetsToTmpFile(const TCustomZoneSetsMap& customZoneSetsMap, std::wstring_view tmpFilePath) - { - json::JsonObject result{}; - - json::JsonArray array; - for (const auto& zoneSet : customZoneSetsMap) - { - CustomZoneSetJSON json{ zoneSet.first, zoneSet.second }; - array.Append(JSONHelpers::CustomZoneSetJSON::ToJson(json)); - } - - result.SetNamedValue(NonLocalizable::CreatedCustomZoneSets, array); - json::to_file(tmpFilePath, result); - } - - std::optional ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath) - { - std::optional result{ std::nullopt }; - if (std::filesystem::exists(tmpFilePath)) - { - if (auto zoneSetJson = json::from_file(tmpFilePath); zoneSetJson.has_value()) - { - if (auto deviceInfo = JSONHelpers::AppliedZonesetsJSON::FromJson(zoneSetJson.value()); deviceInfo.has_value()) - { - result = std::move(deviceInfo); - } - } - } - - DeleteTmpFile(tmpFilePath); - return result; - } - - std::vector ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath) - { - std::vector result; - if (std::filesystem::exists(tmpFilePath)) - { - try - { - if (auto customZoneSetJson = json::from_file(tmpFilePath); customZoneSetJson.has_value()) - { - auto zoneSetArray = customZoneSetJson.value().GetNamedArray(NonLocalizable::CreatedCustomZoneSets); - for (const auto& zoneSet : zoneSetArray) - { - if (auto customZoneSet = JSONHelpers::CustomZoneSetJSON::FromJson(zoneSet.GetObjectW()); customZoneSet.has_value()) - { - result.emplace_back(std::move(*customZoneSet)); - } - } - } - } - catch (const winrt::hresult_error&) - { - } - - DeleteTmpFile(tmpFilePath); - } - return result; - } - - std::vector ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath) - { - std::vector result{}; - if (std::filesystem::exists(tmpFilePath)) - { - auto deletedZoneSetsJson = json::from_file(tmpFilePath); - try - { - auto deletedCustomZoneSets = deletedZoneSetsJson->GetNamedArray(NonLocalizable::DeletedCustomZoneSetsStr); - for (auto zoneSet : deletedCustomZoneSets) - { - std::wstring uuid = L"{" + std::wstring{ zoneSet.GetString() } + L"}"; - result.push_back(uuid); - } - } - catch (const winrt::hresult_error&) - { - } - - DeleteTmpFile(tmpFilePath); - } - - return result; - } } \ No newline at end of file diff --git a/src/modules/fancyzones/lib/JsonHelpers.h b/src/modules/fancyzones/lib/JsonHelpers.h index cf3dceb5782b..6d8c8e2f4ce7 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.h +++ b/src/modules/fancyzones/lib/JsonHelpers.h @@ -59,13 +59,6 @@ namespace JSONHelpers using TDeviceInfoMap = std::unordered_map; using TCustomZoneSetsMap = std::unordered_map; - struct AppliedZonesetsJSON - { - static json::JsonObject ToJson(const TDeviceInfoMap& deviceInfoMap); - static json::JsonObject ToJson(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop); - static std::optional FromJson(const json::JsonObject& json); - }; - json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName); void SaveFancyZonesData(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName, @@ -81,14 +74,4 @@ namespace JSONHelpers TCustomZoneSetsMap ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON); json::JsonArray SerializeCustomZoneSets(const TCustomZoneSetsMap& customZoneSetsMap); - - void SerializeDeviceInfoToTmpFile(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop, std::wstring_view tmpFilePath); - std::optional ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath); - std::vector ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath); - std::vector ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath); - -#if defined(UNIT_TESTS) - void SerializeCustomZoneSetsToTmpFile(const TCustomZoneSetsMap& customZoneSetsMap, std::wstring_view tmpFilePath); -#endif - } From f6786bffc404c2240c0488e9d718ad38823be93f Mon Sep 17 00:00:00 2001 From: Serafima Date: Tue, 15 Dec 2020 22:52:28 +0300 Subject: [PATCH 07/14] updated unit tests --- src/modules/fancyzones/lib/FancyZonesData.h | 5 + .../tests/UnitTests/JsonHelpers.Tests.cpp | 220 ------------------ .../tests/UnitTests/ZoneSet.Spec.cpp | 50 +--- .../tests/UnitTests/ZoneWindow.Spec.cpp | 194 +-------------- 4 files changed, 14 insertions(+), 455 deletions(-) diff --git a/src/modules/fancyzones/lib/FancyZonesData.h b/src/modules/fancyzones/lib/FancyZonesData.h index 7d770631d7c1..a192b05e734f 100644 --- a/src/modules/fancyzones/lib/FancyZonesData.h +++ b/src/modules/fancyzones/lib/FancyZonesData.h @@ -90,6 +90,11 @@ class FancyZonesData deviceInfoMap[deviceId] = data; } + inline void SetCustomZonesets(const std::wstring& uuid, FancyZonesDataTypes::CustomZoneSetData data) + { + customZoneSetsMap[uuid] = data; + } + inline bool ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON) { deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON); diff --git a/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp b/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp index 61b1a1415f03..18ed9467e3ae 100644 --- a/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp +++ b/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp @@ -938,92 +938,6 @@ namespace FancyZonesUnitTests } }; - TEST_CLASS(AppliedZonesetsUnitTests) - { - TEST_METHOD(SingleDevice) - { - const std::wstring deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - const std::wstring zoneUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}"; - const ZoneSetLayoutType type = ZoneSetLayoutType::Custom; - DeviceInfoData data{ ZoneSetData{ zoneUuid, type }, true, 10, 4 }; - - TDeviceInfoMap expected; - expected.insert(std::make_pair(deviceId, data)); - - json::JsonObject json = AppliedZonesetsJSON::ToJson(expected); - auto actual = AppliedZonesetsJSON::FromJson(json); - - Assert::IsTrue(actual.has_value()); - Assert::AreEqual(expected.size(), actual->size()); - for (const auto& exp : expected) - { - Assert::IsTrue(actual->contains(exp.first)); - - const auto act = actual->find(exp.first); - Assert::AreEqual(exp.second.zoneCount, act->second.zoneCount); - Assert::AreEqual(exp.second.showSpacing, act->second.showSpacing); - Assert::AreEqual(exp.second.spacing, act->second.spacing); - Assert::AreEqual(exp.second.activeZoneSet.uuid, act->second.activeZoneSet.uuid); - Assert::AreEqual((int)exp.second.activeZoneSet.type, (int)act->second.activeZoneSet.type); - } - } - - TEST_METHOD (MultipleDevices) - { - TDeviceInfoMap expected; - expected.insert(std::make_pair(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}", DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Columns }, true, 10, 4 })); - expected.insert(std::make_pair(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1538}", DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502905}", ZoneSetLayoutType::Rows }, false, 8, 5 })); - expected.insert(std::make_pair(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1537}", DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502904}", ZoneSetLayoutType::Grid }, true, 9, 6 })); - - json::JsonObject json = AppliedZonesetsJSON::ToJson(expected); - auto actual = AppliedZonesetsJSON::FromJson(json); - - Assert::IsTrue(actual.has_value()); - Assert::AreEqual(expected.size(), actual->size()); - for (const auto& exp : expected) - { - Assert::IsTrue(actual->contains(exp.first)); - - const auto act = actual->find(exp.first); - Assert::AreEqual(exp.second.zoneCount, act->second.zoneCount); - Assert::AreEqual(exp.second.showSpacing, act->second.showSpacing); - Assert::AreEqual(exp.second.spacing, act->second.spacing); - Assert::AreEqual(exp.second.activeZoneSet.uuid, act->second.activeZoneSet.uuid); - Assert::AreEqual((int)exp.second.activeZoneSet.type, (int)act->second.activeZoneSet.type); - } - } - - TEST_METHOD (FromJsonNoDeviceId) - { - json::JsonObject json = json::JsonObject::Parse(L"{\"applied-zonesets\": [{\"device-id\": \"\",\"active-zoneset\": {\"uuid\": \"{81B9FCD3-88CA-4B21-A681-5D1129A1527F}\",\"type\": \"grid\"},\"editor-show-spacing\": true,\"editor-spacing\": 5,\"editor-zone-count\": 4},{\"device-id\": \"\",\"active-zoneset\": {\"uuid\": \"{8110E0D5-4815-4A35-A5AC-DF82A65FF58B}\",\"type\": \"priority-grid\"},\"editor-show-spacing\": false,\"editor-spacing\": 6,\"editor-zone-count\": 2}]}"); - auto actual = AppliedZonesetsJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - Assert::IsTrue(actual->empty()); - } - - TEST_METHOD (FromInvalidJsonNotArray) - { - json::JsonObject json = json::JsonObject::Parse(L"{\"applied-zonesets\": {\"device-id\": \"\",\"active-zoneset\": {\"uuid\": \"{81B9FCD3-88CA-4B21-A681-5D1129A1527F}\",\"type\": \"grid\"},\"editor-show-spacing\": true,\"editor-spacing\": 5,\"editor-zone-count\": 4}}"); - auto actual = AppliedZonesetsJSON::FromJson(json); - Assert::IsFalse(actual.has_value()); - } - - TEST_METHOD (FromEmptyJson) - { - json::JsonObject json = json::JsonObject::Parse(L"{}"); - auto actual = AppliedZonesetsJSON::FromJson(json); - Assert::IsFalse(actual.has_value()); - } - - TEST_METHOD (FromEmptyDeviceArray) - { - json::JsonObject json = json::JsonObject::Parse(L"{\"applied-zonesets\": []}"); - auto actual = AppliedZonesetsJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - Assert::IsTrue(actual->empty()); - } - }; - TEST_CLASS (FancyZonesDataUnitTests) { private: @@ -1186,74 +1100,6 @@ namespace FancyZonesUnitTests compareJsonArrays(expectedDevices, actual); } - TEST_METHOD (DeviceInfoSaveTemp) - { - FancyZonesData data; - data.SetSettingsModulePath(m_moduleName); - - TDeviceInfoMap deviceInfoMap; - DeviceInfoData deviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 }; - deviceInfoMap.insert(std::make_pair(m_defaultDeviceId, deviceInfoData)); - - const std::wstring path = data.zonesSettingsFileName + L".test_tmp"; - JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_defaultVDId, path); - - bool actualFileExists = std::filesystem::exists(path); - Assert::IsTrue(actualFileExists); - - auto expectedData = AppliedZonesetsJSON::ToJson(deviceInfoMap); - auto actualSavedData = json::from_file(path); - std::filesystem::remove(path); //clean up before compare asserts - - Assert::IsTrue(actualSavedData.has_value()); - compareJsonObjects(expectedData, *actualSavedData); - } - - TEST_METHOD (DeviceInfoReadTemp) - { - FancyZonesData data; - data.SetSettingsModulePath(m_moduleName); - - const std::wstring deviceId = m_defaultDeviceId; - DeviceInfoData expected{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 }; - - TDeviceInfoMap expectedDeviceInfoMap; - expectedDeviceInfoMap.insert(std::make_pair(deviceId, expected)); - - const std::wstring path = data.zonesSettingsFileName + L".test_tmp"; - JSONHelpers::SerializeDeviceInfoToTmpFile(expectedDeviceInfoMap, m_defaultVDId, path); - - data.ParseDeviceInfoFromTmpFile(path); - - bool actualFileExists = std::filesystem::exists(path); - if (actualFileExists) - { - std::filesystem::remove(path); //clean up before compare asserts - } - Assert::IsFalse(actualFileExists); - - auto devices = data.GetDeviceInfoMap(); - Assert::AreEqual((size_t)1, devices.size()); - - auto actual = devices.find(deviceId)->second; - Assert::AreEqual(expected.showSpacing, actual.showSpacing); - Assert::AreEqual(expected.spacing, actual.spacing); - Assert::AreEqual(expected.zoneCount, actual.zoneCount); - Assert::AreEqual((int)expected.activeZoneSet.type, (int)actual.activeZoneSet.type); - Assert::AreEqual(expected.activeZoneSet.uuid.c_str(), actual.activeZoneSet.uuid.c_str()); - } - - TEST_METHOD (DeviceInfoReadTempNonexistent) - { - FancyZonesData data; - data.SetSettingsModulePath(m_moduleName); - const std::wstring path = data.zonesSettingsFileName + L".test_tmp"; - data.ParseDeviceInfoFromTmpFile(path); - - auto devices = data.GetDeviceInfoMap(); - Assert::AreEqual((size_t)0, devices.size()); - } - TEST_METHOD (AppZoneHistoryParseSingle) { const std::wstring expectedAppPath = L"appPath"; @@ -1619,72 +1465,6 @@ namespace FancyZonesUnitTests compareJsonArrays(expected, actual); } - TEST_METHOD (CustomZoneSetsReadTemp) - { - //prepare device data - const std::wstring deviceId = L"default_device_id"; - - { - TDeviceInfoMap deviceInfoMap; - DeviceInfoData deviceInfoData { ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 }; - deviceInfoMap.insert(std::make_pair(deviceId, deviceInfoData)); - - const std::wstring deviceInfoPath = m_fzData.zonesSettingsFileName + L".device_info_tmp"; - JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_defaultVDId, deviceInfoPath); - - m_fzData.ParseDeviceInfoFromTmpFile(deviceInfoPath); - std::filesystem::remove(deviceInfoPath); - } - - const std::wstring uuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}"; - const GridLayoutInfo grid(GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 1, - .columns = 3, - .rowsPercents = { 10000 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 } } })); - CustomZoneSetData zoneSetData{ L"name", CustomLayoutType::Grid, grid }; - CustomZoneSetJSON expected{ uuid, zoneSetData }; - - FancyZonesData data; - data.SetSettingsModulePath(m_moduleName); - const std::wstring path = data.zonesSettingsFileName + L".test_tmp"; - - TCustomZoneSetsMap customZoneSets; - customZoneSets.insert(std::make_pair(uuid, zoneSetData)); - JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, path); - - m_fzData.ParseCustomZoneSetsFromTmpFile(path); - - bool actualFileExists = std::filesystem::exists(path); - if (actualFileExists) - { - std::filesystem::remove(path); //clean up before compare asserts - } - Assert::IsFalse(actualFileExists); - - auto devices = m_fzData.GetCustomZoneSetsMap(); - Assert::AreEqual((size_t)1, devices.size()); - - auto actual = devices.find(uuid)->second; - Assert::AreEqual((int)expected.data.type, (int)actual.type); - Assert::AreEqual(expected.data.name.c_str(), actual.name.c_str()); - auto expectedGrid = std::get(expected.data.info); - auto actualGrid = std::get(actual.info); - Assert::AreEqual(expectedGrid.rows(), actualGrid.rows()); - Assert::AreEqual(expectedGrid.columns(), actualGrid.columns()); - } - - TEST_METHOD (CustomZoneSetsReadTempNonexistent) - { - const std::wstring path = m_fzData.zonesSettingsFileName + L".test_tmp"; - const std::wstring deviceId = L"default_device_id"; - - m_fzData.ParseCustomZoneSetsFromTmpFile(path); - auto devices = m_fzData.GetDeviceInfoMap(); - Assert::AreEqual((size_t)0, devices.size()); - } - TEST_METHOD (SetActiveZoneSet) { FancyZonesData data; diff --git a/src/modules/fancyzones/tests/UnitTests/ZoneSet.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/ZoneSet.Spec.cpp index c0982166dd04..1dae84f16353 100644 --- a/src/modules/fancyzones/tests/UnitTests/ZoneSet.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/ZoneSet.Spec.cpp @@ -1047,34 +1047,16 @@ namespace FancyZonesUnitTests TEST_METHOD (CustomZoneFromValidCanvasLayoutInfo) { //prepare device data - { - const std::wstring zoneUuid = L"default_device_id"; - - JSONHelpers::TDeviceInfoMap deviceInfoMap; - deviceInfoMap.insert(std::make_pair(zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 })); - - GUID virtualDesktopId{}; - Assert::IsTrue(VirtualDesktopUtils::GetCurrentVirtualDesktopId(&virtualDesktopId), L"Cannot create virtual desktop id"); - const std::wstring deviceInfoPath = FancyZonesDataInstance().zonesSettingsFileName + L".device_info_tmp"; - JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, virtualDesktopId, deviceInfoPath); - - FancyZonesDataInstance().ParseDeviceInfoFromTmpFile(deviceInfoPath); - std::filesystem::remove(deviceInfoPath); - } + const std::wstring zoneUuid = L"default_device_id"; + FancyZonesDataInstance().SetDeviceInfo(zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 }); //prepare expected data wil::unique_cotaskmem_string uuid; Assert::AreEqual(S_OK, StringFromCLSID(m_id, &uuid)); const CanvasLayoutInfo info{ 123, 321, { CanvasLayoutInfo::Rect{ 0, 0, 100, 100 }, CanvasLayoutInfo::Rect{ 50, 50, 150, 150 } } }; CustomZoneSetData zoneSetData{ L"name", CustomLayoutType::Canvas, info }; - JSONHelpers::CustomZoneSetJSON expected{ uuid.get(), zoneSetData }; - JSONHelpers::TCustomZoneSetsMap customZoneSets; - customZoneSets.insert(std::make_pair(uuid.get(), zoneSetData)); - JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, m_path); - - Assert::IsTrue(std::filesystem::exists(m_path)); - FancyZonesDataInstance().ParseCustomZoneSetsFromTmpFile(m_path); - + FancyZonesDataInstance().SetCustomZonesets(uuid.get(), zoneSetData); + //test const int spacing = 10; const int zoneCount = static_cast(info.zones.size()); @@ -1091,20 +1073,8 @@ namespace FancyZonesUnitTests TEST_METHOD (CustomZoneFromValidGridFullLayoutInfo) { //prepare device data - { - const std::wstring zoneUuid = L"default_device_id"; - - JSONHelpers::TDeviceInfoMap deviceInfoMap; - deviceInfoMap.insert(std::make_pair(zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 })); - - GUID virtualDesktopId{}; - Assert::IsTrue(VirtualDesktopUtils::GetCurrentVirtualDesktopId(&virtualDesktopId), L"Cannot create virtual desktop id"); - const std::wstring deviceInfoPath = FancyZonesDataInstance().zonesSettingsFileName + L".device_info_tmp"; - JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, virtualDesktopId, deviceInfoPath); - - FancyZonesDataInstance().ParseDeviceInfoFromTmpFile(deviceInfoPath); - std::filesystem::remove(deviceInfoPath); - } + const std::wstring zoneUuid = L"default_device_id"; + FancyZonesDataInstance().SetDeviceInfo(zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 }); //prepare expected data wil::unique_cotaskmem_string uuid; @@ -1116,13 +1086,7 @@ namespace FancyZonesUnitTests .columnsPercents = { 2500, 5000, 2500 }, .cellChildMap = { { 0, 1, 2 } } })); CustomZoneSetData zoneSetData{ L"name", CustomLayoutType::Grid, grid }; - JSONHelpers::CustomZoneSetJSON expected{ uuid.get(), zoneSetData }; - JSONHelpers::TCustomZoneSetsMap customZoneSets; - customZoneSets.insert(std::make_pair(uuid.get(), zoneSetData)); - JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, m_path); - - Assert::IsTrue(std::filesystem::exists(m_path)); - FancyZonesDataInstance().ParseCustomZoneSetsFromTmpFile(m_path); + FancyZonesDataInstance().SetCustomZonesets(uuid.get(), zoneSetData); const int spacing = 10; const int zoneCount = grid.rows() * grid.columns(); diff --git a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp index 7a42d783806c..ddfddf607f5f 100644 --- a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp @@ -174,192 +174,6 @@ namespace FancyZonesUnitTests Assert::AreEqual(activeZoneSet->GetZones().size(), static_cast(3)); } - TEST_METHOD(CreateZoneWindowWithActiveZoneTmpFile) - { - using namespace FancyZonesDataTypes; - - const auto activeZoneSetTempPath = m_fancyZonesData.activeZoneSetTmpFileName; - - for (int type = static_cast(ZoneSetLayoutType::Focus); type < static_cast(ZoneSetLayoutType::Custom); type++) - { - const auto expectedZoneSet = ZoneSetData{ Helpers::CreateGuidString(), static_cast(type) }; - const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 }; - const auto deviceInfo = JSONHelpers::DeviceInfoJSON{ m_uniqueId.str(), data }; - const auto json = JSONHelpers::DeviceInfoJSON::ToJson(deviceInfo); - json::to_file(activeZoneSetTempPath, json); - - m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath); - - //temp file read on initialization - auto actual = MakeZoneWindow(winrt::make_self().get(), m_hInst, m_monitor, m_uniqueId.str(), {}); - - testZoneWindow(actual); - - Assert::IsNotNull(actual->ActiveZoneSet()); - } - } - - TEST_METHOD(CreateZoneWindowWithActiveCustomZoneTmpFile) - { - using namespace FancyZonesDataTypes; - - const auto activeZoneSetTempPath = m_fancyZonesData.activeZoneSetTmpFileName; - - const ZoneSetLayoutType type = ZoneSetLayoutType::Custom; - const auto expectedZoneSet = ZoneSetData{ Helpers::CreateGuidString(), type }; - const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 }; - JSONHelpers::TDeviceInfoMap deviceInfoMap; - deviceInfoMap.insert(std::make_pair(m_uniqueId.str(), data)); - JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_virtualDesktopGuid, activeZoneSetTempPath); - - m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath); - - //temp file read on initialization - auto actual = MakeZoneWindow(winrt::make_self().get(), m_hInst, m_monitor, m_uniqueId.str(), {}); - - testZoneWindow(actual); - - //custom zone needs temp file for applied zone - Assert::IsNotNull(actual->ActiveZoneSet()); - const auto actualZoneSet = actual->ActiveZoneSet()->GetZones(); - Assert::AreEqual((size_t)0, actualZoneSet.size()); - } - - TEST_METHOD(CreateZoneWindowWithActiveCustomZoneAppliedTmpFile) - { - using namespace FancyZonesDataTypes; - - //save required data - const auto activeZoneSetTempPath = m_fancyZonesData.activeZoneSetTmpFileName; - const auto appliedZoneSetTempPath = m_fancyZonesData.appliedZoneSetTmpFileName; - - const ZoneSetLayoutType type = ZoneSetLayoutType::Custom; - const auto customSetGuid = Helpers::CreateGuidString(); - const auto expectedZoneSet = ZoneSetData{ customSetGuid, type }; - const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 }; - JSONHelpers::TDeviceInfoMap deviceInfoMap; - deviceInfoMap.insert(std::make_pair(m_uniqueId.str(), data)); - JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_virtualDesktopGuid, activeZoneSetTempPath); - - const auto info = CanvasLayoutInfo{ - 100, 100, std::vector{ CanvasLayoutInfo::Rect{ 0, 0, 100, 100 } } - }; - const auto customZoneData = CustomZoneSetData{ L"name", CustomLayoutType::Canvas, info }; - auto customZoneJson = JSONHelpers::CustomZoneSetJSON::ToJson(JSONHelpers::CustomZoneSetJSON{ customSetGuid, customZoneData }); - JSONHelpers::TCustomZoneSetsMap customZoneSets; - customZoneSets.insert(std::make_pair(customSetGuid, customZoneData)); - JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, appliedZoneSetTempPath); - m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath); - m_fancyZonesData.ParseCustomZoneSetsFromTmpFile(appliedZoneSetTempPath); - - //temp file read on initialization - auto actual = MakeZoneWindow(winrt::make_self().get(), m_hInst, m_monitor, m_uniqueId.str(), {}); - - testZoneWindow(actual); - - //custom zone needs temp file for applied zone - Assert::IsNotNull(actual->ActiveZoneSet()); - const auto actualZoneSet = actual->ActiveZoneSet()->GetZones(); - Assert::AreEqual((size_t)1, actualZoneSet.size()); - } - - TEST_METHOD(CreateZoneWindowWithActiveCustomZoneAppliedTmpFileWithDeletedCustomZones) - { - using namespace FancyZonesDataTypes; - - //save required data - const auto activeZoneSetTempPath = m_fancyZonesData.activeZoneSetTmpFileName; - const auto appliedZoneSetTempPath = m_fancyZonesData.appliedZoneSetTmpFileName; - const auto deletedZonesTempPath = m_fancyZonesData.deletedCustomZoneSetsTmpFileName; - - const ZoneSetLayoutType type = ZoneSetLayoutType::Custom; - const auto customSetGuid = Helpers::CreateGuidString(); - const auto expectedZoneSet = ZoneSetData{ customSetGuid, type }; - const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 }; - JSONHelpers::TDeviceInfoMap deviceInfoMap; - deviceInfoMap.insert(std::make_pair(m_uniqueId.str(), data)); - JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_virtualDesktopGuid, activeZoneSetTempPath); - - const auto info = CanvasLayoutInfo{ - 100, 100, std::vector{ CanvasLayoutInfo::Rect{ 0, 0, 100, 100 } } - }; - const auto customZoneData = CustomZoneSetData{ L"name", CustomLayoutType::Canvas, info }; - const auto customZoneSet = JSONHelpers::CustomZoneSetJSON{ customSetGuid, customZoneData }; - auto customZoneJson = JSONHelpers::CustomZoneSetJSON::ToJson(customZoneSet); - JSONHelpers::TCustomZoneSetsMap customZoneSets; - customZoneSets.insert(std::make_pair(customSetGuid, customZoneData)); - JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, appliedZoneSetTempPath); - - //save same zone as deleted - json::JsonObject deletedCustomZoneSets = {}; - json::JsonArray zonesArray{}; - zonesArray.Append(json::JsonValue::CreateStringValue(customZoneSet.uuid.substr(1, customZoneSet.uuid.size() - 2).c_str())); - deletedCustomZoneSets.SetNamedValue(L"deleted-custom-zone-sets", zonesArray); - json::to_file(deletedZonesTempPath, deletedCustomZoneSets); - - m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath); - m_fancyZonesData.ParseDeletedCustomZoneSetsFromTmpFile(deletedZonesTempPath); - m_fancyZonesData.ParseCustomZoneSetsFromTmpFile(appliedZoneSetTempPath); - - //temp file read on initialization - auto actual = MakeZoneWindow(winrt::make_self().get(), m_hInst, m_monitor, m_uniqueId.str(), {}); - - testZoneWindow(actual); - - Assert::IsNotNull(actual->ActiveZoneSet()); - const auto actualZoneSet = actual->ActiveZoneSet()->GetZones(); - Assert::AreEqual((size_t)1, actualZoneSet.size()); - } - - TEST_METHOD(CreateZoneWindowWithActiveCustomZoneAppliedTmpFileWithUnusedDeletedCustomZones) - { - using namespace FancyZonesDataTypes; - - //save required data - const auto activeZoneSetTempPath = m_fancyZonesData.activeZoneSetTmpFileName; - const auto appliedZoneSetTempPath = m_fancyZonesData.appliedZoneSetTmpFileName; - const auto deletedZonesTempPath = m_fancyZonesData.deletedCustomZoneSetsTmpFileName; - - const ZoneSetLayoutType type = ZoneSetLayoutType::Custom; - const auto customSetGuid = Helpers::CreateGuidString(); - const auto expectedZoneSet = ZoneSetData{ customSetGuid, type }; - const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 }; - JSONHelpers::TDeviceInfoMap deviceInfoMap; - deviceInfoMap.insert(std::make_pair(m_uniqueId.str(), data)); - JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_virtualDesktopGuid, activeZoneSetTempPath); - - const auto info = CanvasLayoutInfo{ - 100, 100, std::vector{ CanvasLayoutInfo::Rect{ 0, 0, 100, 100 } } - }; - const auto customZoneData = CustomZoneSetData{ L"name", CustomLayoutType::Canvas, info }; - const auto customZoneSet = JSONHelpers::CustomZoneSetJSON{ customSetGuid, customZoneData }; - auto customZoneJson = JSONHelpers::CustomZoneSetJSON::ToJson(customZoneSet); - JSONHelpers::TCustomZoneSetsMap customZoneSets; - customZoneSets.insert(std::make_pair(customSetGuid, customZoneData)); - JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, appliedZoneSetTempPath); - - //save different zone as deleted - json::JsonObject deletedCustomZoneSets = {}; - json::JsonArray zonesArray{}; - const auto uuid = Helpers::CreateGuidString(); - zonesArray.Append(json::JsonValue::CreateStringValue(uuid.substr(1, uuid.size() - 2).c_str())); - deletedCustomZoneSets.SetNamedValue(L"deleted-custom-zone-sets", zonesArray); - json::to_file(deletedZonesTempPath, deletedCustomZoneSets); - - m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath); - m_fancyZonesData.ParseDeletedCustomZoneSetsFromTmpFile(deletedZonesTempPath); - m_fancyZonesData.ParseCustomZoneSetsFromTmpFile(appliedZoneSetTempPath); - - //temp file read on initialization - auto actual = MakeZoneWindow(winrt::make_self().get(), m_hInst, m_monitor, m_uniqueId.str(), {}); - - testZoneWindow(actual); - - Assert::IsNotNull(actual->ActiveZoneSet()); - const auto actualZoneSet = actual->ActiveZoneSet()->GetZones(); - Assert::AreEqual((size_t)1, actualZoneSet.size()); - } - TEST_METHOD (CreateZoneWindowClonedFromParent) { using namespace FancyZonesDataTypes; @@ -372,12 +186,8 @@ namespace FancyZonesUnitTests const auto parentDeviceInfo = DeviceInfoData{ parentZoneSet, true, spacing, zoneCount }; m_fancyZonesData.SetDeviceInfo(m_parentUniqueId.str(), parentDeviceInfo); - winrt::com_ptr zoneWindowHost = winrt::make_self(); - auto parentZoneWindow = MakeZoneWindow(zoneWindowHost.get(), m_hInst, m_monitor, m_parentUniqueId.str(), {}); - zoneWindowHost->m_zoneWindow = parentZoneWindow.get(); - - // newWorkArea = true - zoneWindow will be cloned from parent - auto actualZoneWindow = MakeZoneWindow(winrt::make_self().get(), m_hInst, m_monitor, m_uniqueId.str(), m_parentUniqueId.str()); + // newWorkArea = false - zoneWindow won't be cloned from parent + auto actualZoneWindow = MakeZoneWindow(winrt::make_self().get(), m_hInst, m_monitor, m_uniqueId.str(), {}); Assert::IsNotNull(actualZoneWindow->ActiveZoneSet()); const auto actualZoneSet = actualZoneWindow->ActiveZoneSet()->GetZones(); From 553b713160e9fdbedb6c43b955b8ce6b7279ad09 Mon Sep 17 00:00:00 2001 From: Serafima Date: Tue, 15 Dec 2020 18:04:36 +0300 Subject: [PATCH 08/14] refactoring --- .../Utils/FancyZonesEditorIO.cs | 50 ++++++------------- 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index 3445acf7eb85..1df964050d65 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -79,15 +79,15 @@ public override string ToString() } } - private struct ActiveZoneSetWrapper + private struct DeviceWrapper { - public string Uuid { get; set; } + public struct ActiveZoneSetWrapper + { + public string Uuid { get; set; } - public string Type { get; set; } - } + public string Type { get; set; } + } - private struct DeviceWrapper - { public string DeviceId { get; set; } public ActiveZoneSetWrapper ActiveZoneset { get; set; } @@ -101,19 +101,19 @@ private struct DeviceWrapper public int EditorSensitivityRadius { get; set; } } - private struct CanvasZoneWrapper + private struct CanvasInfoWrapper { - public int X { get; set; } + public struct CanvasZoneWrapper + { + public int X { get; set; } - public int Y { get; set; } + public int Y { get; set; } public int Width { get; set; } - public int Height { get; set; } - } + public int Height { get; set; } + } - private struct CanvasInfoWrapper - { public int RefWidth { get; set; } public int RefHeight { get; set; } @@ -142,29 +142,7 @@ private struct CustomLayoutWrapper public string Type { get; set; } - public JsonElement Info { get; set; } - } - - private struct CustomCanvasLayoutWrapper - { - public string Uuid { get; set; } - - public string Name { get; set; } - - public string Type { get; set; } - - public CanvasInfoWrapper Info { get; set; } - } - - private struct CustomGridLayoutWrapper - { - public string Uuid { get; set; } - - public string Name { get; set; } - - public string Type { get; set; } - - public GridInfoWrapper Info { get; set; } + public JsonElement Info { get; set; } // CanvasInfoWrapper or GridInfoWrapper } private struct ZoneSettingsWrapper From 6bde7d39a619f82e0f689da2e848c0e63f6663e2 Mon Sep 17 00:00:00 2001 From: Serafima Date: Tue, 15 Dec 2020 23:00:23 +0300 Subject: [PATCH 09/14] parsing with retry loop --- .../editor/FancyZonesEditor/App.xaml.cs | 39 ++- .../Properties/Resources.Designer.cs | 27 +++ .../Properties/Resources.resx | 9 + .../Utils/FancyZonesEditorIO.cs | 224 ++++++++++-------- 4 files changed, 205 insertions(+), 94 deletions(-) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs index 72e79706594d..759074dccd6e 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs @@ -9,6 +9,8 @@ using System.IO; using System.Linq; using System.Text; +using System.Threading; +using System.Threading.Tasks; using System.Windows; using FancyZonesEditor.Utils; using ManagedCommon; @@ -87,7 +89,42 @@ private void OnStartup(object sender, StartupEventArgs e) _themeManager = new ThemeManager(this); FancyZonesEditorIO.ParseCommandLineArguments(); - FancyZonesEditorIO.ParseZoneSettings(); + + var parseResult = FancyZonesEditorIO.ParseZoneSettings(); + + // 10ms retry loop with 1 second timeout + if (!parseResult.Item1) + { + CancellationTokenSource ts = new CancellationTokenSource(); + Task t = Task.Run(() => + { + while (!parseResult.Item1 && !ts.IsCancellationRequested) + { + Task.Delay(10).Wait(); + parseResult = FancyZonesEditorIO.ParseZoneSettings(); + } + }); + + try + { + bool result = t.Wait(1000, ts.Token); + ts.Cancel(); + } + catch (OperationCanceledException) + { + ts.Dispose(); + } + } + + // Error message if parsing failed + if (!parseResult.Item1) + { + string message = parseResult.Item2 + Environment.NewLine + Environment.NewLine + FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_User_Choice; + if (MessageBox.Show(message, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Title, MessageBoxButton.YesNo) == MessageBoxResult.No) + { + Environment.Exit(0); + } + } MainWindowSettingsModel settings = ((App)Current).MainWindowSettings; settings.UpdateSelectedLayoutModel(); diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs index bf2cc65c3a9c..0aab0c75a1d7 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs @@ -348,6 +348,33 @@ public static string Error_Parsing_Device_Info { } } + /// + /// Looks up a localized string similar to 'zones-settings.json' contains malformed data.. + /// + public static string Error_Parsing_Zones_Settings_Malformed_Data { + get { + return ResourceManager.GetString("Error_Parsing_Zones_Settings_Malformed_Data", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Editor settings parsing error.. + /// + public static string Error_Parsing_Zones_Settings_Title { + get { + return ResourceManager.GetString("Error_Parsing_Zones_Settings_Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Would you like to continue? Malformed data will be lost.. + /// + public static string Error_Parsing_Zones_Settings_User_Choice { + get { + return ResourceManager.GetString("Error_Parsing_Zones_Settings_User_Choice", resourceCulture); + } + } + /// /// Looks up a localized string similar to Error persisting custom layout. /// diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx index 514f0d6804d6..1dc1ca816696 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx @@ -307,4 +307,13 @@ To merge zones, select the zones and click "merge". Delete zone A tooltip on a button that allows the user to delete a zone + + 'zones-settings.json' contains malformed data. + + + Editor settings parsing error. + + + Would you like to continue? Malformed data will be lost. + \ No newline at end of file diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index 1df964050d65..3cee8011766b 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -109,7 +109,7 @@ public struct CanvasZoneWrapper public int Y { get; set; } - public int Width { get; set; } + public int Width { get; set; } public int Height { get; set; } } @@ -313,104 +313,29 @@ public static void ParseCommandLineArguments() } } - public void ParseZoneSettings() + public Tuple ParseZoneSettings() { - try + if (_fileSystem.File.Exists(FancyZonesSettingsFile)) { - if (_fileSystem.File.Exists(FancyZonesSettingsFile)) + try { - Stream inputStream = _fileSystem.File.Open(FancyZonesSettingsFile, FileMode.Open); - StreamReader reader = new StreamReader(inputStream); - string data = reader.ReadToEnd(); - inputStream.Close(); + var zoneSettings = ReadZoneSettings(FancyZonesSettingsFile); - var zoneSettings = JsonSerializer.Deserialize(data, _options); + bool devicesParsingResult = SetDevices(zoneSettings.Devices); + bool customZonesParsingResult = SetCustomLayouts(zoneSettings.CustomZoneSets); - // Set devices - var monitors = App.Overlay.Monitors; - foreach (var device in zoneSettings.Devices) + if (!devicesParsingResult || !customZonesParsingResult) { - var settings = new LayoutSettings - { - ZonesetUuid = device.ActiveZoneset.Uuid, - ShowSpacing = device.EditorShowSpacing, - Spacing = device.EditorSpacing, - Type = JsonTagToLayoutType(device.ActiveZoneset.Type), - ZoneCount = device.EditorZoneCount, - SensitivityRadius = device.EditorSensitivityRadius, - }; - - if (!App.Overlay.SpanZonesAcrossMonitors) - { - foreach (Monitor monitor in monitors) - { - if (monitor.Device.Id == device.DeviceId) - { - monitor.Settings = settings; - break; - } - } - } - else - { - bool isLayoutMultiMonitor = device.DeviceId.StartsWith(MultiMonitorId); - if (isLayoutMultiMonitor) - { - // one zoneset for all desktops - App.Overlay.Monitors[App.Overlay.CurrentDesktop].Settings = settings; - App.Overlay.Monitors[App.Overlay.CurrentDesktop].Device.Id = device.DeviceId; - break; - } - } - } - - // Set layouts - MainWindowSettingsModel.CustomModels.Clear(); - MainWindowSettingsModel.CustomModels.Add(MainWindowSettingsModel.BlankModel); - foreach (var zoneSet in zoneSettings.CustomZoneSets) - { - LayoutModel layout; - if (zoneSet.Type == CanvasLayoutModel.ModelTypeID) - { - var info = JsonSerializer.Deserialize(zoneSet.Info.GetRawText(), _options); - - var zones = new List(); - foreach (var zone in info.Zones) - { - zones.Add(new Int32Rect { X = (int)zone.X, Y = (int)zone.Y, Width = (int)zone.Width, Height = (int)zone.Height }); - } - - layout = new CanvasLayoutModel(zoneSet.Uuid, zoneSet.Name, LayoutType.Custom, zones, info.RefWidth, info.RefHeight); - } - else if (zoneSet.Type == GridLayoutModel.ModelTypeID) - { - var info = JsonSerializer.Deserialize(zoneSet.Info.GetRawText(), _options); - - var cells = new int[info.Rows, info.Columns]; - for (int row = 0; row < info.Rows; row++) - { - for (int column = 0; column < info.Columns; column++) - { - cells[row, column] = info.CellChildMap[row][column]; - } - } - - layout = new GridLayoutModel(zoneSet.Uuid, zoneSet.Name, LayoutType.Custom, info.Rows, info.Columns, info.RowsPercentage, info.ColumnsPercentage, cells); - } - else - { - // Error - continue; - } - - MainWindowSettingsModel.CustomModels.Add(layout); + return new Tuple(false, Properties.Resources.Error_Parsing_Zones_Settings_Malformed_Data); } } + catch (Exception ex) + { + return new Tuple(false, ex.Message); + } } - catch (Exception ex) - { - App.ShowExceptionMessageBox(Properties.Resources.Error_Parsing_Device_Info, ex); - } + + return new Tuple(true, string.Empty); } public void SerializeZoneSettings() @@ -431,7 +356,7 @@ public void SerializeZoneSettings() zoneSettings.Devices.Add(new DeviceWrapper { DeviceId = monitor.Device.Id, - ActiveZoneset = new ActiveZoneSetWrapper + ActiveZoneset = new DeviceWrapper.ActiveZoneSetWrapper { Uuid = zoneset.ZonesetUuid, Type = LayoutTypeToJsonTag(zoneset.Type), @@ -469,12 +394,12 @@ public void SerializeZoneSettings() { RefWidth = (int)canvasRect.Width, RefHeight = (int)canvasRect.Height, - Zones = new List(), + Zones = new List(), }; foreach (var zone in canvasLayout.Zones) { - wrapper.Zones.Add(new CanvasZoneWrapper + wrapper.Zones.Add(new CanvasInfoWrapper.CanvasZoneWrapper { X = zone.X, Y = zone.Y, @@ -541,6 +466,119 @@ public void SerializeZoneSettings() } } + private ZoneSettingsWrapper ReadZoneSettings(string fileName) + { + Stream inputStream = _fileSystem.File.Open(fileName, FileMode.Open); + StreamReader reader = new StreamReader(inputStream); + string data = reader.ReadToEnd(); + inputStream.Close(); + + return JsonSerializer.Deserialize(data, _options); + } + + private bool SetDevices(List devices) + { + bool result = true; + var monitors = App.Overlay.Monitors; + foreach (var device in devices) + { + if (device.DeviceId == null || device.DeviceId.Length == 0 || device.ActiveZoneset.Uuid == null || device.ActiveZoneset.Uuid.Length == 0) + { + result = false; + continue; + } + + var settings = new LayoutSettings + { + ZonesetUuid = device.ActiveZoneset.Uuid, + ShowSpacing = device.EditorShowSpacing, + Spacing = device.EditorSpacing, + Type = JsonTagToLayoutType(device.ActiveZoneset.Type), + ZoneCount = device.EditorZoneCount, + SensitivityRadius = device.EditorSensitivityRadius, + }; + + if (!App.Overlay.SpanZonesAcrossMonitors) + { + foreach (Monitor monitor in monitors) + { + if (monitor.Device.Id == device.DeviceId) + { + monitor.Settings = settings; + break; + } + } + } + else + { + bool isLayoutMultiMonitor = device.DeviceId.StartsWith(MultiMonitorId); + if (isLayoutMultiMonitor) + { + // one zoneset for all desktops + App.Overlay.Monitors[App.Overlay.CurrentDesktop].Settings = settings; + App.Overlay.Monitors[App.Overlay.CurrentDesktop].Device.Id = device.DeviceId; + break; + } + } + } + + return result; + } + + private bool SetCustomLayouts(List customLayouts) + { + MainWindowSettingsModel.CustomModels.Clear(); + MainWindowSettingsModel.CustomModels.Add(MainWindowSettingsModel.BlankModel); + bool result = true; + + foreach (var zoneSet in customLayouts) + { + if (zoneSet.Uuid == null || zoneSet.Uuid.Length == 0) + { + result = false; + continue; + } + + LayoutModel layout; + if (zoneSet.Type == CanvasLayoutModel.ModelTypeID) + { + var info = JsonSerializer.Deserialize(zoneSet.Info.GetRawText(), _options); + + var zones = new List(); + foreach (var zone in info.Zones) + { + zones.Add(new Int32Rect { X = (int)zone.X, Y = (int)zone.Y, Width = (int)zone.Width, Height = (int)zone.Height }); + } + + layout = new CanvasLayoutModel(zoneSet.Uuid, zoneSet.Name, LayoutType.Custom, zones, info.RefWidth, info.RefHeight); + } + else if (zoneSet.Type == GridLayoutModel.ModelTypeID) + { + var info = JsonSerializer.Deserialize(zoneSet.Info.GetRawText(), _options); + + var cells = new int[info.Rows, info.Columns]; + for (int row = 0; row < info.Rows; row++) + { + for (int column = 0; column < info.Columns; column++) + { + cells[row, column] = info.CellChildMap[row][column]; + } + } + + layout = new GridLayoutModel(zoneSet.Uuid, zoneSet.Name, LayoutType.Custom, info.Rows, info.Columns, info.RowsPercentage, info.ColumnsPercentage, cells); + } + else + { + result = false; + continue; + } + + MainWindowSettingsModel.CustomModels.Add(layout); + } + + return result; + } + private LayoutType JsonTagToLayoutType(string tag) { LayoutType type = LayoutType.Blank; From 429deb0ec4f61ea3ab62727516f772d7963a3532 Mon Sep 17 00:00:00 2001 From: Serafima Date: Tue, 15 Dec 2020 23:33:23 +0300 Subject: [PATCH 10/14] fixes --- .../Models/MainWindowSettingsModel.cs | 4 ++- .../Utils/FancyZonesEditorIO.cs | 27 +++++++++++-------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/MainWindowSettingsModel.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/MainWindowSettingsModel.cs index 65d3797db10a..294579fe507d 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/MainWindowSettingsModel.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/MainWindowSettingsModel.cs @@ -354,10 +354,12 @@ public static CanvasLayoutModel BlankModel { get { - return _blankCustomModel; + return _blankModel; } } + private static CanvasLayoutModel _blankModel = new CanvasLayoutModel(string.Empty, LayoutType.Blank); + public static bool IsPredefinedLayout(LayoutModel model) { return model.Type != LayoutType.Custom; diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index 3cee8011766b..31d6d4365559 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -528,7 +528,6 @@ private bool SetDevices(List devices) private bool SetCustomLayouts(List customLayouts) { MainWindowSettingsModel.CustomModels.Clear(); - MainWindowSettingsModel.CustomModels.Add(MainWindowSettingsModel.BlankModel); bool result = true; foreach (var zoneSet in customLayouts) @@ -609,17 +608,23 @@ private LayoutType JsonTagToLayoutType(string tag) private string LayoutTypeToJsonTag(LayoutType type) { - return type switch + switch (type) { - LayoutType.Blank => BlankJsonTag, - LayoutType.Focus => FocusJsonTag, - LayoutType.Rows => RowsJsonTag, - LayoutType.Columns => ColumnsJsonTag, - LayoutType.Grid => GridJsonTag, - LayoutType.PriorityGrid => PriorityGridJsonTag, - LayoutType.Custom => CustomJsonTag, - _ => string.Empty, - }; + case LayoutType.Focus: + return FocusJsonTag; + case LayoutType.Columns: + return ColumnsJsonTag; + case LayoutType.Rows: + return RowsJsonTag; + case LayoutType.Grid: + return GridJsonTag; + case LayoutType.PriorityGrid: + return PriorityGridJsonTag; + case LayoutType.Custom: + return CustomJsonTag; + default: + return string.Empty; + } } private static string ParsingCmdArgsErrorReport(string args, int count, string targetMonitorName, List monitorData, List monitors) From 5e4725531776dfd74f0dba1331876decc2a3d4f8 Mon Sep 17 00:00:00 2001 From: Serafima Date: Wed, 16 Dec 2020 00:03:05 +0300 Subject: [PATCH 11/14] unit test fix --- src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp index ddfddf607f5f..dd2f037befe1 100644 --- a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp @@ -187,7 +187,7 @@ namespace FancyZonesUnitTests m_fancyZonesData.SetDeviceInfo(m_parentUniqueId.str(), parentDeviceInfo); // newWorkArea = false - zoneWindow won't be cloned from parent - auto actualZoneWindow = MakeZoneWindow(winrt::make_self().get(), m_hInst, m_monitor, m_uniqueId.str(), {}); + auto actualZoneWindow = MakeZoneWindow(winrt::make_self().get(), m_hInst, m_monitor, m_uniqueId.str(), m_parentUniqueId.str()); Assert::IsNotNull(actualZoneWindow->ActiveZoneSet()); const auto actualZoneSet = actualZoneWindow->ActiveZoneSet()->GetZones(); From 45b90d0e3d607de829815dcae88a260fa6c09129 Mon Sep 17 00:00:00 2001 From: Serafima Date: Wed, 16 Dec 2020 14:34:23 +0300 Subject: [PATCH 12/14] log parsing error --- .../editor/FancyZonesEditor/App.xaml.cs | 23 ++++++++-- .../Utils/FancyZonesEditorIO.cs | 42 +++++++++++++++---- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs index 759074dccd6e..cebcdd72c35c 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs @@ -43,6 +43,9 @@ public partial class App : Application private const string CrashReportDynamicAssemblyTag = "dynamic assembly doesn't have location"; private const string CrashReportLocationNullTag = "location is null or empty"; + private const string ParsingErrorReportTag = "Settings parsing error"; + private const string ParsingErrorDataTag = "Data: "; + public MainWindowSettingsModel MainWindowSettings { get; } public static FancyZonesEditorIO FancyZonesEditorIO { get; private set; } @@ -93,12 +96,12 @@ private void OnStartup(object sender, StartupEventArgs e) var parseResult = FancyZonesEditorIO.ParseZoneSettings(); // 10ms retry loop with 1 second timeout - if (!parseResult.Item1) + if (!parseResult.Result) { CancellationTokenSource ts = new CancellationTokenSource(); Task t = Task.Run(() => { - while (!parseResult.Item1 && !ts.IsCancellationRequested) + while (!parseResult.Result && !ts.IsCancellationRequested) { Task.Delay(10).Wait(); parseResult = FancyZonesEditorIO.ParseZoneSettings(); @@ -117,13 +120,25 @@ private void OnStartup(object sender, StartupEventArgs e) } // Error message if parsing failed - if (!parseResult.Item1) + if (!parseResult.Result) { - string message = parseResult.Item2 + Environment.NewLine + Environment.NewLine + FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_User_Choice; + var sb = new StringBuilder(); + sb.AppendLine(); + sb.AppendLine("## " + ParsingErrorReportTag); + sb.AppendLine(); + sb.AppendLine(parseResult.Message); + sb.AppendLine(); + sb.AppendLine(ParsingErrorDataTag); + sb.AppendLine(parseResult.ManlformedData); + + string message = parseResult.Message + Environment.NewLine + Environment.NewLine + FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_User_Choice; if (MessageBox.Show(message, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Title, MessageBoxButton.YesNo) == MessageBoxResult.No) { + ShowExceptionReportMessageBox(sb.ToString()); Environment.Exit(0); } + + ShowExceptionReportMessageBox(sb.ToString()); } MainWindowSettingsModel settings = ((App)Current).MainWindowSettings; diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index 31d6d4365559..380dae44bf58 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -152,6 +152,22 @@ private struct ZoneSettingsWrapper public List CustomZoneSets { get; set; } } + public struct ParsingResult + { + public bool Result { get; } + + public string Message { get; } + + public string ManlformedData { get; } + + public ParsingResult(bool result, string message = "", string data = "") + { + Result = result; + Message = message; + ManlformedData = data; + } + } + public FancyZonesEditorIO() { var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); @@ -313,29 +329,40 @@ public static void ParseCommandLineArguments() } } - public Tuple ParseZoneSettings() + public ParsingResult ParseZoneSettings() { if (_fileSystem.File.Exists(FancyZonesSettingsFile)) { + ZoneSettingsWrapper zoneSettings; + string settingsString = string.Empty; + try { - var zoneSettings = ReadZoneSettings(FancyZonesSettingsFile); + settingsString = ReadZoneSettings(FancyZonesSettingsFile); + zoneSettings = JsonSerializer.Deserialize(settingsString, _options); + } + catch (Exception ex) + { + return new ParsingResult(false, ex.Message, settingsString); + } + try + { bool devicesParsingResult = SetDevices(zoneSettings.Devices); bool customZonesParsingResult = SetCustomLayouts(zoneSettings.CustomZoneSets); if (!devicesParsingResult || !customZonesParsingResult) { - return new Tuple(false, Properties.Resources.Error_Parsing_Zones_Settings_Malformed_Data); + return new ParsingResult(false, Properties.Resources.Error_Parsing_Zones_Settings_Malformed_Data, settingsString); } } catch (Exception ex) { - return new Tuple(false, ex.Message); + return new ParsingResult(false, ex.Message, settingsString); } } - return new Tuple(true, string.Empty); + return new ParsingResult(true); } public void SerializeZoneSettings() @@ -466,14 +493,13 @@ public void SerializeZoneSettings() } } - private ZoneSettingsWrapper ReadZoneSettings(string fileName) + private string ReadZoneSettings(string fileName) { Stream inputStream = _fileSystem.File.Open(fileName, FileMode.Open); StreamReader reader = new StreamReader(inputStream); string data = reader.ReadToEnd(); inputStream.Close(); - - return JsonSerializer.Deserialize(data, _options); + return data; } private bool SetDevices(List devices) From f3d97ce96625bdc283601ba94c73e82b6f1f2eca Mon Sep 17 00:00:00 2001 From: Serafima Date: Wed, 16 Dec 2020 14:54:44 +0300 Subject: [PATCH 13/14] spelling fix --- src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs | 2 +- .../editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs index cebcdd72c35c..e54e56799f30 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs @@ -129,7 +129,7 @@ private void OnStartup(object sender, StartupEventArgs e) sb.AppendLine(parseResult.Message); sb.AppendLine(); sb.AppendLine(ParsingErrorDataTag); - sb.AppendLine(parseResult.ManlformedData); + sb.AppendLine(parseResult.MalformedData); string message = parseResult.Message + Environment.NewLine + Environment.NewLine + FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_User_Choice; if (MessageBox.Show(message, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Title, MessageBoxButton.YesNo) == MessageBoxResult.No) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index 380dae44bf58..14f322102565 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -158,13 +158,13 @@ public struct ParsingResult public string Message { get; } - public string ManlformedData { get; } + public string MalformedData { get; } public ParsingResult(bool result, string message = "", string data = "") { Result = result; Message = message; - ManlformedData = data; + MalformedData = data; } } From 8af951cb062e5dbda27a31fab63b3632ff6fe43e Mon Sep 17 00:00:00 2001 From: Seraphima Zykova Date: Wed, 16 Dec 2020 18:07:11 +0300 Subject: [PATCH 14/14] added TODO Co-authored-by: Enrico Giordani --- src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs index e54e56799f30..42f84b80d316 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs @@ -134,6 +134,7 @@ private void OnStartup(object sender, StartupEventArgs e) string message = parseResult.Message + Environment.NewLine + Environment.NewLine + FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_User_Choice; if (MessageBox.Show(message, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Title, MessageBoxButton.YesNo) == MessageBoxResult.No) { + // TODO: log error ShowExceptionReportMessageBox(sb.ToString()); Environment.Exit(0); }