mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-06 03:07:04 +02:00
Migrate FancyZones data persisting from Registry to JSON file (#1194)
* Migrate FancyZones data persisting from Registry to JSON file * Address PR comment: Remove redundant check * Addres PR comment: Remove unused Dpi and add CmdArgs enum * Address PR comment: Make methods const and inline * Address PR comments: Expose GenerateUniqueId function and use const ref instead of passing wstring by value * Address PR comment: Use lamdba as callback * Address PR comment: Move GenerateUniqueId to ZoneWindowUtils namespace * Address PR comment: Use regular comparison instead of std::wstring::compare * Address PR comment: Use std::wstring_view for tmp file paths * Address PR comment: Use scoped lock when accessing member data * Address PR comment: Remove typedefs to increase code readability * Address PR comment: removed nullptr checks with corresponding tests * Address PR comment: Move ZoneSet object instead of copying * Address PR comment: Make FancyZonesData instance const where possible * Remove unnecessary gutter variable during calculating zone coordinates * Remove uneeded subclass * Avoid unnecessary copying and reserve space for vector if possible * Save FancyZones data after exiting editor * App zone history (#18) * added window and zone set ids to app zone history * Rename JSON file * Remove AppZoneHistory migration * Move parsing of ZoneWindow independent temp files outside of it * Unit tests update (#19) * check device existence in map * updated ZoneSet tests * updated JsonHelpers tests * Use single zone count information * Remove uneeded tests * Remove one more test * Remove uneeded line * Address PR comments - Missing whitespace * Update zoneset data for new virtual desktops (#21) * update active zone set with actual data * Introduce Blank zone set (used to indicate that no layout applied yet). Move parsing completely outside of ZoneWindow. * Fix unit tests to match modifications in implementation * Fix applying layouts on startup (second monitor) Co-authored-by: vldmr11080 <57061786+vldmr11080@users.noreply.github.com> Co-authored-by: Seraphima <zykovas91@gmail.com>
This commit is contained in:
@@ -15,8 +15,6 @@ namespace FancyZonesEditor
|
||||
{
|
||||
public Settings ZoneSettings { get; }
|
||||
|
||||
private ushort _idInitial = 0;
|
||||
|
||||
public App()
|
||||
{
|
||||
ZoneSettings = new Settings();
|
||||
@@ -24,37 +22,29 @@ namespace FancyZonesEditor
|
||||
|
||||
private void OnStartup(object sender, StartupEventArgs e)
|
||||
{
|
||||
if (e.Args.Length > 1)
|
||||
{
|
||||
ushort.TryParse(e.Args[1], out _idInitial);
|
||||
}
|
||||
|
||||
LayoutModel foundModel = null;
|
||||
|
||||
if (_idInitial != 0)
|
||||
foreach (LayoutModel model in ZoneSettings.DefaultModels)
|
||||
{
|
||||
foreach (LayoutModel model in ZoneSettings.DefaultModels)
|
||||
if (model.Type == Settings.ActiveZoneSetLayoutType)
|
||||
{
|
||||
if (model.Id == _idInitial)
|
||||
// found match
|
||||
foundModel = model;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundModel == null)
|
||||
{
|
||||
foreach (LayoutModel model in Settings.CustomModels)
|
||||
{
|
||||
if ("{" + model.Guid.ToString().ToUpper() + "}" == Settings.ActiveZoneSetUUid.ToUpper())
|
||||
{
|
||||
// found match
|
||||
foundModel = model;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundModel == null)
|
||||
{
|
||||
foreach (LayoutModel model in ZoneSettings.CustomModels)
|
||||
{
|
||||
if (model.Id == _idInitial)
|
||||
{
|
||||
// found match
|
||||
foundModel = model;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundModel == null)
|
||||
|
||||
@@ -18,8 +18,11 @@ namespace FancyZonesEditor
|
||||
|
||||
private readonly Settings _settings = ((App)Application.Current).ZoneSettings;
|
||||
private LayoutPreview _layoutPreview;
|
||||
|
||||
private UserControl _editor;
|
||||
|
||||
private static MainWindow _mainWindow = new MainWindow();
|
||||
|
||||
public Int32Rect[] GetZoneRects()
|
||||
{
|
||||
if (_editor != null)
|
||||
@@ -79,27 +82,23 @@ namespace FancyZonesEditor
|
||||
|
||||
public void ShowLayoutPicker()
|
||||
{
|
||||
DataContext = null;
|
||||
|
||||
_editor = null;
|
||||
_layoutPreview = new LayoutPreview
|
||||
{
|
||||
IsActualSize = true,
|
||||
Opacity = 0.5,
|
||||
};
|
||||
|
||||
Content = _layoutPreview;
|
||||
|
||||
MainWindow window = new MainWindow
|
||||
{
|
||||
Owner = this,
|
||||
ShowActivated = true,
|
||||
Topmost = true,
|
||||
};
|
||||
window.Show();
|
||||
_mainWindow.Owner = this;
|
||||
_mainWindow.ShowActivated = true;
|
||||
_mainWindow.Topmost = true;
|
||||
_mainWindow.Show();
|
||||
|
||||
// window is set to topmost to make sure it shows on top of PowerToys settings page
|
||||
// we can reset topmost flag now
|
||||
window.Topmost = false;
|
||||
_mainWindow.Topmost = false;
|
||||
}
|
||||
|
||||
// These event handlers are used to track the current state of the Shift and Ctrl keys on the keyboard
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
@@ -194,6 +195,9 @@
|
||||
<PackageReference Include="MahApps.Metro">
|
||||
<Version>2.0.0-alpha0455</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Text.Json">
|
||||
<Version>4.6.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="StyleCop.Analyzers">
|
||||
<Version>1.1.118</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
@@ -208,4 +212,4 @@
|
||||
<Resource Include="images\Merge.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace FancyZonesEditor
|
||||
public const int MaxZones = 40;
|
||||
private readonly Settings _settings = ((App)Application.Current).ZoneSettings;
|
||||
private static readonly string _defaultNamePrefix = "Custom Layout ";
|
||||
private bool _editing = false;
|
||||
|
||||
public int WrapPanelItemSize { get; set; } = 262;
|
||||
|
||||
@@ -67,7 +66,7 @@ namespace FancyZonesEditor
|
||||
{
|
||||
WindowLayout window = new WindowLayout();
|
||||
window.Show();
|
||||
Close();
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void LayoutItem_Click(object sender, MouseButtonEventArgs e)
|
||||
@@ -95,12 +94,11 @@ namespace FancyZonesEditor
|
||||
}
|
||||
|
||||
model.IsSelected = false;
|
||||
_editing = true;
|
||||
Close();
|
||||
Hide();
|
||||
|
||||
bool isPredefinedLayout = Settings.IsPredefinedLayout(model);
|
||||
|
||||
if (!_settings.CustomModels.Contains(model) || isPredefinedLayout)
|
||||
if (!Settings.CustomModels.Contains(model) || isPredefinedLayout)
|
||||
{
|
||||
if (isPredefinedLayout)
|
||||
{
|
||||
@@ -110,7 +108,7 @@ namespace FancyZonesEditor
|
||||
}
|
||||
|
||||
int maxCustomIndex = 0;
|
||||
foreach (LayoutModel customModel in _settings.CustomModels)
|
||||
foreach (LayoutModel customModel in Settings.CustomModels)
|
||||
{
|
||||
string name = customModel.Name;
|
||||
if (name.StartsWith(_defaultNamePrefix))
|
||||
@@ -165,10 +163,8 @@ namespace FancyZonesEditor
|
||||
|
||||
private void OnClosing(object sender, EventArgs e)
|
||||
{
|
||||
if (!_editing)
|
||||
{
|
||||
EditorOverlay.Current.Close();
|
||||
}
|
||||
LayoutModel.SerializeDeletedCustomZoneSets();
|
||||
EditorOverlay.Current.Close();
|
||||
}
|
||||
|
||||
private void OnInitialized(object sender, EventArgs e)
|
||||
@@ -178,7 +174,7 @@ namespace FancyZonesEditor
|
||||
|
||||
private void SetSelectedItem()
|
||||
{
|
||||
foreach (LayoutModel model in _settings.CustomModels)
|
||||
foreach (LayoutModel model in Settings.CustomModels)
|
||||
{
|
||||
if (model.IsSelected)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Windows;
|
||||
|
||||
namespace FancyZonesEditor.Models
|
||||
@@ -11,40 +14,27 @@ namespace FancyZonesEditor.Models
|
||||
// Free form Layout Model, which specifies independent zone rects
|
||||
public class CanvasLayoutModel : LayoutModel
|
||||
{
|
||||
private static readonly ushort _latestVersion = 0;
|
||||
|
||||
public CanvasLayoutModel(ushort version, string name, ushort id, byte[] data)
|
||||
: base(name, id)
|
||||
public CanvasLayoutModel(string uuid, string name, LayoutType type, int referenceWidth, int referenceHeight, IList<Int32Rect> zones)
|
||||
: base(uuid, name, type)
|
||||
{
|
||||
if (version == _latestVersion)
|
||||
{
|
||||
Load(data);
|
||||
}
|
||||
_referenceWidth = referenceWidth;
|
||||
_referenceHeight = referenceHeight;
|
||||
Zones = zones;
|
||||
}
|
||||
|
||||
public CanvasLayoutModel(string name, ushort id, int referenceWidth, int referenceHeight)
|
||||
: base(name, id)
|
||||
public CanvasLayoutModel(string name, LayoutType type, int referenceWidth, int referenceHeight)
|
||||
: base(name, type)
|
||||
{
|
||||
// Initialize Reference Size
|
||||
_referenceWidth = referenceWidth;
|
||||
_referenceHeight = referenceHeight;
|
||||
}
|
||||
|
||||
public CanvasLayoutModel(string name, ushort id)
|
||||
: base(name, id)
|
||||
{
|
||||
}
|
||||
|
||||
public CanvasLayoutModel(string name)
|
||||
: base(name)
|
||||
{
|
||||
}
|
||||
|
||||
public CanvasLayoutModel()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
// ReferenceWidth - the reference width for the layout rect that all Zones are relative to
|
||||
public int ReferenceWidth
|
||||
{
|
||||
@@ -104,26 +94,6 @@ namespace FancyZonesEditor.Models
|
||||
FirePropertyChanged("Zones");
|
||||
}
|
||||
|
||||
private void Load(byte[] data)
|
||||
{
|
||||
// Initialize this CanvasLayoutModel based on the given persistence data
|
||||
// Skip version (2 bytes), id (2 bytes), and type (1 bytes)
|
||||
int i = 5;
|
||||
_referenceWidth = (data[i++] * 256) + data[i++];
|
||||
_referenceHeight = (data[i++] * 256) + data[i++];
|
||||
|
||||
int count = data[i++];
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
Zones.Add(new Int32Rect(
|
||||
(data[i++] * 256) + data[i++],
|
||||
(data[i++] * 256) + data[i++],
|
||||
(data[i++] * 256) + data[i++],
|
||||
(data[i++] * 256) + data[i++]));
|
||||
}
|
||||
}
|
||||
|
||||
// Clone
|
||||
// Implements the LayoutModel.Clone abstract method
|
||||
// Clones the data from this CanvasLayoutModel to a new CanvasLayoutModel
|
||||
@@ -143,44 +113,50 @@ namespace FancyZonesEditor.Models
|
||||
return layout;
|
||||
}
|
||||
|
||||
// GetPersistData
|
||||
// Implements the LayoutModel.GetPersistData abstract method
|
||||
// Returns the state of this GridLayoutModel in persisted format
|
||||
protected override byte[] GetPersistData()
|
||||
// PersistData
|
||||
// Implements the LayoutModel.PersistData abstract method
|
||||
protected override void PersistData()
|
||||
{
|
||||
byte[] data = new byte[10 + (Zones.Count * 8)];
|
||||
int i = 0;
|
||||
|
||||
// Common persisted values between all layout types
|
||||
data[i++] = (byte)(_latestVersion / 256);
|
||||
data[i++] = (byte)(_latestVersion % 256);
|
||||
data[i++] = 1; // LayoutModelType: 1 == CanvasLayoutModel
|
||||
data[i++] = (byte)(Id / 256);
|
||||
data[i++] = (byte)(Id % 256);
|
||||
|
||||
// End common
|
||||
data[i++] = (byte)(_referenceWidth / 256);
|
||||
data[i++] = (byte)(_referenceWidth % 256);
|
||||
data[i++] = (byte)(_referenceHeight / 256);
|
||||
data[i++] = (byte)(_referenceHeight % 256);
|
||||
data[i++] = (byte)Zones.Count;
|
||||
|
||||
foreach (Int32Rect rect in Zones)
|
||||
FileStream outputStream = File.Open(Settings.AppliedZoneSetTmpFile, FileMode.Create);
|
||||
JsonWriterOptions writerOptions = new JsonWriterOptions
|
||||
{
|
||||
data[i++] = (byte)(rect.X / 256);
|
||||
data[i++] = (byte)(rect.X % 256);
|
||||
SkipValidation = true,
|
||||
};
|
||||
using (var writer = new Utf8JsonWriter(outputStream, writerOptions))
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
writer.WriteString("uuid", "{" + Guid.ToString().ToUpper() + "}");
|
||||
writer.WriteString("name", Name);
|
||||
|
||||
data[i++] = (byte)(rect.Y / 256);
|
||||
data[i++] = (byte)(rect.Y % 256);
|
||||
writer.WriteString("type", "canvas");
|
||||
|
||||
data[i++] = (byte)(rect.Width / 256);
|
||||
data[i++] = (byte)(rect.Width % 256);
|
||||
writer.WriteStartObject("info");
|
||||
|
||||
data[i++] = (byte)(rect.Height / 256);
|
||||
data[i++] = (byte)(rect.Height % 256);
|
||||
writer.WriteNumber("ref-width", _referenceWidth);
|
||||
writer.WriteNumber("ref-height", _referenceHeight);
|
||||
|
||||
writer.WriteStartArray("zones");
|
||||
foreach (Int32Rect rect in Zones)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
writer.WriteNumber("X", rect.X);
|
||||
writer.WriteNumber("Y", rect.Y);
|
||||
writer.WriteNumber("width", rect.Width);
|
||||
writer.WriteNumber("height", rect.Height);
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
writer.WriteEndArray();
|
||||
|
||||
// end info object
|
||||
writer.WriteEndObject();
|
||||
|
||||
// end root object
|
||||
writer.WriteEndObject();
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
return data;
|
||||
outputStream.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,20 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FancyZonesEditor.Models
|
||||
{
|
||||
// GridLayoutModel
|
||||
// Grid-styled Layout Model, which specifies rows, columns, percentage sizes, and row/column spans
|
||||
public class GridLayoutModel : LayoutModel
|
||||
{
|
||||
private static readonly ushort _latestVersion = 0;
|
||||
|
||||
// Rows - number of rows in the Grid
|
||||
public int Rows
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace FancyZonesEditor.Models
|
||||
{
|
||||
// GridLayoutModel
|
||||
// Grid-styled Layout Model, which specifies rows, columns, percentage sizes, and row/column spans
|
||||
public class GridLayoutModel : LayoutModel
|
||||
{
|
||||
// Rows - number of rows in the Grid
|
||||
public int Rows
|
||||
{
|
||||
get
|
||||
{
|
||||
return _rows;
|
||||
@@ -22,19 +23,19 @@ namespace FancyZonesEditor.Models
|
||||
|
||||
set
|
||||
{
|
||||
if (_rows != value)
|
||||
{
|
||||
_rows = value;
|
||||
FirePropertyChanged("Rows");
|
||||
if (_rows != value)
|
||||
{
|
||||
_rows = value;
|
||||
FirePropertyChanged("Rows");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int _rows = 1;
|
||||
|
||||
// Columns - number of columns in the Grid
|
||||
public int Columns
|
||||
{
|
||||
}
|
||||
|
||||
private int _rows = 1;
|
||||
|
||||
// Columns - number of columns in the Grid
|
||||
public int Columns
|
||||
{
|
||||
get
|
||||
{
|
||||
return _cols;
|
||||
@@ -42,19 +43,19 @@ namespace FancyZonesEditor.Models
|
||||
|
||||
set
|
||||
{
|
||||
if (_cols != value)
|
||||
{
|
||||
_cols = value;
|
||||
FirePropertyChanged("Columns");
|
||||
if (_cols != value)
|
||||
{
|
||||
_cols = value;
|
||||
FirePropertyChanged("Columns");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int _cols = 1;
|
||||
|
||||
// CellChildMap - represents which "children" belong in which grid cells;
|
||||
// shows spanning children by the same index appearing in adjacent cells
|
||||
// TODO: ideally no setter here - this means moving logic like "split" over to model
|
||||
}
|
||||
|
||||
private int _cols = 1;
|
||||
|
||||
// CellChildMap - represents which "children" belong in which grid cells;
|
||||
// shows spanning children by the same index appearing in adjacent cells
|
||||
// TODO: ideally no setter here - this means moving logic like "split" over to model
|
||||
public int[,] CellChildMap { get; set; }
|
||||
|
||||
// RowPercents - represents the %age height of each row in the grid
|
||||
@@ -69,179 +70,159 @@ namespace FancyZonesEditor.Models
|
||||
public IList<int> FreeZones { get; } = new List<int>();
|
||||
|
||||
public GridLayoutModel()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public GridLayoutModel(string name)
|
||||
: base(name)
|
||||
{
|
||||
}
|
||||
|
||||
public GridLayoutModel(string name, ushort id)
|
||||
: base(name, id)
|
||||
{
|
||||
}
|
||||
|
||||
public GridLayoutModel(ushort version, string name, ushort id, byte[] data)
|
||||
: base(name, id)
|
||||
{
|
||||
if (version == _latestVersion)
|
||||
{
|
||||
Reload(data);
|
||||
}
|
||||
public GridLayoutModel(string name, LayoutType type)
|
||||
: base(name, type)
|
||||
{
|
||||
}
|
||||
|
||||
public void Reload(byte[] data)
|
||||
{
|
||||
// Skip version (2 bytes), id (2 bytes), and type (1 bytes)
|
||||
int i = 5;
|
||||
|
||||
Rows = data[i++];
|
||||
Columns = data[i++];
|
||||
|
||||
RowPercents = new int[Rows];
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
RowPercents[row] = (data[i++] * 256) + data[i++];
|
||||
}
|
||||
|
||||
ColumnPercents = new int[Columns];
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
ColumnPercents[col] = (data[i++] * 256) + data[i++];
|
||||
}
|
||||
|
||||
CellChildMap = new int[Rows, Columns];
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
CellChildMap[row, col] = data[i++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone
|
||||
// Implements the LayoutModel.Clone abstract method
|
||||
// Clones the data from this GridLayoutModel to a new GridLayoutModel
|
||||
public override LayoutModel Clone()
|
||||
{
|
||||
GridLayoutModel layout = new GridLayoutModel(Name);
|
||||
int rows = Rows;
|
||||
int cols = Columns;
|
||||
|
||||
layout.Rows = rows;
|
||||
layout.Columns = cols;
|
||||
|
||||
int[,] cellChildMap = new int[rows, cols];
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
cellChildMap[row, col] = CellChildMap[row, col];
|
||||
}
|
||||
}
|
||||
|
||||
layout.CellChildMap = cellChildMap;
|
||||
|
||||
int[] rowPercents = new int[rows];
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
rowPercents[row] = RowPercents[row];
|
||||
}
|
||||
|
||||
layout.RowPercents = rowPercents;
|
||||
|
||||
int[] colPercents = new int[cols];
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
colPercents[col] = ColumnPercents[col];
|
||||
}
|
||||
|
||||
layout.ColumnPercents = colPercents;
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
// GetPersistData
|
||||
// Implements the LayoutModel.GetPersistData abstract method
|
||||
// Returns the state of this GridLayoutModel in persisted format
|
||||
protected override byte[] GetPersistData()
|
||||
{
|
||||
int rows = Rows;
|
||||
int cols = Columns;
|
||||
|
||||
int[,] cellChildMap;
|
||||
|
||||
if (FreeZones.Count == 0)
|
||||
{
|
||||
// no unused indices -- so we can just use the _cellChildMap as is
|
||||
cellChildMap = CellChildMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
// compress cellChildMap to not have gaps for unused child indices;
|
||||
List<int> mapping = new List<int>();
|
||||
|
||||
cellChildMap = new int[rows, cols];
|
||||
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
int source = CellChildMap[row, col];
|
||||
|
||||
int index = mapping.IndexOf(source);
|
||||
if (index == -1)
|
||||
{
|
||||
index = mapping.Count;
|
||||
mapping.Add(source);
|
||||
}
|
||||
|
||||
cellChildMap[row, col] = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte[] data = new byte[7 + (Rows * 2) + (Columns * 2) + (Rows * Columns)];
|
||||
|
||||
int i = 0;
|
||||
public GridLayoutModel(string uuid, string name, LayoutType type, int rows, int cols, int[] rowPercents, int[] colsPercents, int[,] cellChildMap)
|
||||
: base(uuid, name, type)
|
||||
{
|
||||
_rows = rows;
|
||||
_cols = cols;
|
||||
RowPercents = rowPercents;
|
||||
ColumnPercents = colsPercents;
|
||||
CellChildMap = cellChildMap;
|
||||
}
|
||||
|
||||
// Common persisted values between all layout types
|
||||
data[i++] = (byte)(_latestVersion / 256);
|
||||
data[i++] = (byte)(_latestVersion % 256);
|
||||
data[i++] = 0; // LayoutModelType: 0 == GridLayoutModel
|
||||
data[i++] = (byte)(Id / 256);
|
||||
data[i++] = (byte)(Id % 256);
|
||||
|
||||
// End common
|
||||
data[i++] = (byte)Rows;
|
||||
data[i++] = (byte)Columns;
|
||||
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
int rowPercent = RowPercents[row];
|
||||
data[i++] = (byte)(rowPercent / 256);
|
||||
data[i++] = (byte)(rowPercent % 256);
|
||||
}
|
||||
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
int colPercent = ColumnPercents[col];
|
||||
data[i++] = (byte)(colPercent / 256);
|
||||
data[i++] = (byte)(colPercent % 256);
|
||||
}
|
||||
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
data[i++] = (byte)cellChildMap[row, col];
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Reload(byte[] data)
|
||||
{
|
||||
// Skip version (2 bytes), id (2 bytes), and type (1 bytes)
|
||||
int i = 5;
|
||||
|
||||
Rows = data[i++];
|
||||
Columns = data[i++];
|
||||
|
||||
RowPercents = new int[Rows];
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
RowPercents[row] = (data[i++] * 256) + data[i++];
|
||||
}
|
||||
|
||||
ColumnPercents = new int[Columns];
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
ColumnPercents[col] = (data[i++] * 256) + data[i++];
|
||||
}
|
||||
|
||||
CellChildMap = new int[Rows, Columns];
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
CellChildMap[row, col] = data[i++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone
|
||||
// Implements the LayoutModel.Clone abstract method
|
||||
// Clones the data from this GridLayoutModel to a new GridLayoutModel
|
||||
public override LayoutModel Clone()
|
||||
{
|
||||
GridLayoutModel layout = new GridLayoutModel(Name);
|
||||
int rows = Rows;
|
||||
int cols = Columns;
|
||||
|
||||
layout.Rows = rows;
|
||||
layout.Columns = cols;
|
||||
|
||||
int[,] cellChildMap = new int[rows, cols];
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
cellChildMap[row, col] = CellChildMap[row, col];
|
||||
}
|
||||
}
|
||||
|
||||
layout.CellChildMap = cellChildMap;
|
||||
|
||||
int[] rowPercents = new int[rows];
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
rowPercents[row] = RowPercents[row];
|
||||
}
|
||||
|
||||
layout.RowPercents = rowPercents;
|
||||
|
||||
int[] colPercents = new int[cols];
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
colPercents[col] = ColumnPercents[col];
|
||||
}
|
||||
|
||||
layout.ColumnPercents = colPercents;
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
// PersistData
|
||||
// Implements the LayoutModel.PersistData abstract method
|
||||
protected override void PersistData()
|
||||
{
|
||||
FileStream outputStream = File.Open(Settings.AppliedZoneSetTmpFile, FileMode.Create);
|
||||
using (var writer = new Utf8JsonWriter(outputStream, options: default))
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
writer.WriteString("uuid", "{" + Guid.ToString().ToUpper() + "}");
|
||||
writer.WriteString("name", Name);
|
||||
|
||||
writer.WriteString("type", "grid");
|
||||
|
||||
writer.WriteStartObject("info");
|
||||
|
||||
writer.WriteNumber("rows", Rows);
|
||||
writer.WriteNumber("columns", Columns);
|
||||
|
||||
writer.WriteStartArray("rows-percentage");
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
writer.WriteNumberValue(RowPercents[row]);
|
||||
}
|
||||
|
||||
writer.WriteEndArray();
|
||||
|
||||
writer.WriteStartArray("columns-percentage");
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
writer.WriteNumberValue(ColumnPercents[col]);
|
||||
}
|
||||
|
||||
writer.WriteEndArray();
|
||||
|
||||
writer.WriteStartArray("cell-child-map");
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
writer.WriteNumberValue(CellChildMap[row, col]);
|
||||
}
|
||||
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
|
||||
writer.WriteEndArray();
|
||||
|
||||
// end info object
|
||||
writer.WriteEndObject();
|
||||
|
||||
// end root object
|
||||
writer.WriteEndObject();
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
outputStream.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,28 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// 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.InteropServices;
|
||||
using Microsoft.Win32;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Windows;
|
||||
|
||||
namespace FancyZonesEditor.Models
|
||||
{
|
||||
public enum LayoutType
|
||||
{
|
||||
Blank = -1,
|
||||
Focus,
|
||||
Columns,
|
||||
Rows,
|
||||
Grid,
|
||||
PriorityGrid,
|
||||
Custom,
|
||||
}
|
||||
|
||||
// Base LayoutModel
|
||||
// Manages common properties and base persistence
|
||||
public abstract class LayoutModel : INotifyPropertyChanged
|
||||
@@ -19,18 +32,30 @@ namespace FancyZonesEditor.Models
|
||||
|
||||
protected LayoutModel()
|
||||
{
|
||||
_guid = Guid.NewGuid();
|
||||
Type = LayoutType.Custom;
|
||||
}
|
||||
|
||||
protected LayoutModel(string name)
|
||||
: this()
|
||||
{
|
||||
_guid = Guid.NewGuid();
|
||||
Name = name;
|
||||
}
|
||||
|
||||
protected LayoutModel(string name, ushort id)
|
||||
protected LayoutModel(string uuid, string name, LayoutType type)
|
||||
: this()
|
||||
{
|
||||
_guid = Guid.Parse(uuid);
|
||||
Name = name;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
protected LayoutModel(string name, LayoutType type)
|
||||
: this(name)
|
||||
{
|
||||
_id = id;
|
||||
_guid = Guid.NewGuid();
|
||||
Type = type;
|
||||
}
|
||||
|
||||
// Name - the display name for this layout model - is also used as the key in the registry
|
||||
@@ -53,22 +78,17 @@ namespace FancyZonesEditor.Models
|
||||
|
||||
private string _name;
|
||||
|
||||
// Id - the unique ID for this layout model - is used to connect fancy zones' ZonesSets with the editor's Layouts
|
||||
// - note: 0 means this is a new layout, which means it will have its ID auto-assigned on persist
|
||||
public ushort Id
|
||||
public LayoutType Type { get; set; }
|
||||
|
||||
public Guid Guid
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_id == 0)
|
||||
{
|
||||
_id = ++_maxId;
|
||||
}
|
||||
|
||||
return _id;
|
||||
return _guid;
|
||||
}
|
||||
}
|
||||
|
||||
private ushort _id = 0;
|
||||
private Guid _guid;
|
||||
|
||||
// IsSelected (not-persisted) - tracks whether or not this LayoutModel is selected in the picker
|
||||
// TODO: once we switch to a picker per monitor, we need to move this state to the view
|
||||
@@ -103,51 +123,99 @@ namespace FancyZonesEditor.Models
|
||||
// Removes this Layout from the registry and the loaded CustomModels list
|
||||
public void Delete()
|
||||
{
|
||||
RegistryKey key = Registry.CurrentUser.OpenSubKey(_registryPath, true);
|
||||
if (key != null)
|
||||
{
|
||||
key.DeleteValue(Name);
|
||||
}
|
||||
|
||||
int i = _customModels.IndexOf(this);
|
||||
if (i != -1)
|
||||
{
|
||||
_customModels.RemoveAt(i);
|
||||
_deletedCustomModels.Add(Guid.ToString().ToUpper());
|
||||
}
|
||||
}
|
||||
|
||||
// Loads all the Layouts persisted under the Layouts key in the registry
|
||||
public static void SerializeDeletedCustomZoneSets()
|
||||
{
|
||||
FileStream outputStream = File.Open(Settings.CustomZoneSetsTmpFile, FileMode.Create);
|
||||
var writer = new Utf8JsonWriter(outputStream, options: default);
|
||||
writer.WriteStartObject();
|
||||
writer.WriteStartArray("deleted-custom-zone-sets");
|
||||
foreach (string zoneSet in _deletedCustomModels)
|
||||
{
|
||||
writer.WriteStringValue(zoneSet);
|
||||
}
|
||||
|
||||
writer.WriteEndArray();
|
||||
writer.WriteEndObject();
|
||||
writer.Flush();
|
||||
outputStream.Close();
|
||||
}
|
||||
|
||||
// Loads all the custom Layouts from tmp file passed by FancuZonesLib
|
||||
public static ObservableCollection<LayoutModel> LoadCustomModels()
|
||||
{
|
||||
_customModels = new ObservableCollection<LayoutModel>();
|
||||
|
||||
RegistryKey key = Registry.CurrentUser.OpenSubKey(_registryPath);
|
||||
if (key != null)
|
||||
FileStream inputStream = File.Open(Settings.CustomZoneSetsTmpFile, FileMode.Open);
|
||||
var jsonObject = JsonDocument.Parse(inputStream, options: default);
|
||||
JsonElement.ArrayEnumerator customZoneSetsEnumerator = jsonObject.RootElement.GetProperty("custom-zone-sets").EnumerateArray();
|
||||
while (customZoneSetsEnumerator.MoveNext())
|
||||
{
|
||||
foreach (string name in key.GetValueNames())
|
||||
var current = customZoneSetsEnumerator.Current;
|
||||
string name = current.GetProperty("name").GetString();
|
||||
string type = current.GetProperty("type").GetString();
|
||||
string uuid = current.GetProperty("uuid").GetString();
|
||||
var info = current.GetProperty("info");
|
||||
if (type.Equals("grid"))
|
||||
{
|
||||
LayoutModel model = null;
|
||||
byte[] data = (byte[])Registry.GetValue(_fullRegistryPath, name, null);
|
||||
|
||||
ushort version = (ushort)((data[0] * 256) + data[1]);
|
||||
byte type = data[2];
|
||||
ushort id = (ushort)((data[3] * 256) + data[4]);
|
||||
|
||||
switch (type)
|
||||
int rows = info.GetProperty("rows").GetInt32();
|
||||
int columns = info.GetProperty("columns").GetInt32();
|
||||
int[] rowsPercentage = new int[rows];
|
||||
JsonElement.ArrayEnumerator rowsPercentageEnumerator = info.GetProperty("rows-percentage").EnumerateArray();
|
||||
int i = 0;
|
||||
while (rowsPercentageEnumerator.MoveNext())
|
||||
{
|
||||
case 0: model = new GridLayoutModel(version, name, id, data); break;
|
||||
case 1: model = new CanvasLayoutModel(version, name, id, data); break;
|
||||
rowsPercentage[i++] = rowsPercentageEnumerator.Current.GetInt32();
|
||||
}
|
||||
|
||||
if (model != null)
|
||||
i = 0;
|
||||
int[] columnsPercentage = new int[columns];
|
||||
JsonElement.ArrayEnumerator columnsPercentageEnumerator = info.GetProperty("columns-percentage").EnumerateArray();
|
||||
while (columnsPercentageEnumerator.MoveNext())
|
||||
{
|
||||
if (_maxId < id)
|
||||
columnsPercentage[i++] = columnsPercentageEnumerator.Current.GetInt32();
|
||||
}
|
||||
|
||||
i = 0;
|
||||
JsonElement.ArrayEnumerator cellChildMapRows = info.GetProperty("cell-child-map").EnumerateArray();
|
||||
int[,] cellChildMap = new int[rows, columns];
|
||||
while (cellChildMapRows.MoveNext())
|
||||
{
|
||||
int j = 0;
|
||||
JsonElement.ArrayEnumerator cellChildMapRowElems = cellChildMapRows.Current.EnumerateArray();
|
||||
while (cellChildMapRowElems.MoveNext())
|
||||
{
|
||||
_maxId = id;
|
||||
cellChildMap[i, j++] = cellChildMapRowElems.Current.GetInt32();
|
||||
}
|
||||
|
||||
_customModels.Add(model);
|
||||
i++;
|
||||
}
|
||||
|
||||
_customModels.Add(new GridLayoutModel(uuid, name, LayoutType.Custom, rows, columns, rowsPercentage, columnsPercentage, cellChildMap));
|
||||
}
|
||||
else if (type.Equals("canvas"))
|
||||
{
|
||||
int referenceWidth = info.GetProperty("ref-width").GetInt32();
|
||||
int referenceHeight = info.GetProperty("ref-height").GetInt32();
|
||||
JsonElement.ArrayEnumerator zonesEnumerator = info.GetProperty("zones").EnumerateArray();
|
||||
IList<Int32Rect> zones = new List<Int32Rect>();
|
||||
while (zonesEnumerator.MoveNext())
|
||||
{
|
||||
int x = zonesEnumerator.Current.GetProperty("X").GetInt32();
|
||||
int y = zonesEnumerator.Current.GetProperty("Y").GetInt32();
|
||||
int width = zonesEnumerator.Current.GetProperty("width").GetInt32();
|
||||
int height = zonesEnumerator.Current.GetProperty("height").GetInt32();
|
||||
zones.Add(new Int32Rect(x, y, width, height));
|
||||
}
|
||||
|
||||
_customModels.Add(new CanvasLayoutModel(uuid, name, LayoutType.Custom, referenceWidth, referenceHeight, zones));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,55 +223,63 @@ namespace FancyZonesEditor.Models
|
||||
}
|
||||
|
||||
private static ObservableCollection<LayoutModel> _customModels = null;
|
||||
|
||||
private static ushort _maxId = 0;
|
||||
private static List<string> _deletedCustomModels = new List<string>();
|
||||
|
||||
// Callbacks that the base LayoutModel makes to derived types
|
||||
protected abstract byte[] GetPersistData();
|
||||
protected abstract void PersistData();
|
||||
|
||||
public abstract LayoutModel Clone();
|
||||
|
||||
public void Persist(System.Windows.Int32Rect[] zones)
|
||||
{
|
||||
// Persist the editor data
|
||||
Registry.SetValue(_fullRegistryPath, Name, GetPersistData(), Microsoft.Win32.RegistryValueKind.Binary);
|
||||
PersistData();
|
||||
Apply(zones);
|
||||
}
|
||||
|
||||
public void Apply(System.Windows.Int32Rect[] zones)
|
||||
{
|
||||
// Persist the zone data back into FZ
|
||||
var module = Native.LoadLibrary("fancyzones.dll");
|
||||
if (module == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pfn = Native.GetProcAddress(module, "PersistZoneSet");
|
||||
if (pfn == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale all the zones to the DPI and then pack them up to be marshalled.
|
||||
int zoneCount = zones.Length;
|
||||
var zoneArray = new int[zoneCount * 4];
|
||||
for (int i = 0; i < zones.Length; i++)
|
||||
{
|
||||
var left = (int)(zones[i].X * Settings.Dpi);
|
||||
var top = (int)(zones[i].Y * Settings.Dpi);
|
||||
var right = left + (int)(zones[i].Width * Settings.Dpi);
|
||||
var bottom = top + (int)(zones[i].Height * Settings.Dpi);
|
||||
FileStream outputStream = File.Open(Settings.ActiveZoneSetTmpFile, FileMode.Create);
|
||||
var writer = new Utf8JsonWriter(outputStream, options: default);
|
||||
|
||||
var index = i * 4;
|
||||
zoneArray[index] = left;
|
||||
zoneArray[index + 1] = top;
|
||||
zoneArray[index + 2] = right;
|
||||
zoneArray[index + 3] = bottom;
|
||||
writer.WriteStartObject();
|
||||
writer.WriteString("device-id", Settings.UniqueKey);
|
||||
|
||||
writer.WriteStartObject("active-zoneset");
|
||||
writer.WriteString("uuid", "{" + Guid.ToString().ToUpper() + "}");
|
||||
switch (Type)
|
||||
{
|
||||
case LayoutType.Focus:
|
||||
writer.WriteString("type", "focus");
|
||||
break;
|
||||
case LayoutType.Rows:
|
||||
writer.WriteString("type", "rows");
|
||||
break;
|
||||
case LayoutType.Columns:
|
||||
writer.WriteString("type", "columns");
|
||||
break;
|
||||
case LayoutType.Grid:
|
||||
writer.WriteString("type", "grid");
|
||||
break;
|
||||
case LayoutType.PriorityGrid:
|
||||
writer.WriteString("type", "priority-grid");
|
||||
break;
|
||||
case LayoutType.Custom:
|
||||
writer.WriteString("type", "custom");
|
||||
break;
|
||||
}
|
||||
|
||||
var persistZoneSet = Marshal.GetDelegateForFunctionPointer<Native.PersistZoneSet>(pfn);
|
||||
persistZoneSet(Settings.UniqueKey, Settings.WorkAreaKey, Settings.Monitor, _id, zoneCount, zoneArray);
|
||||
writer.WriteEndObject();
|
||||
|
||||
Settings settings = ((App)Application.Current).ZoneSettings;
|
||||
|
||||
writer.WriteBoolean("editor-show-spacing", settings.ShowSpacing);
|
||||
writer.WriteNumber("editor-spacing", settings.Spacing);
|
||||
writer.WriteNumber("editor-zone-count", settings.ZoneCount);
|
||||
|
||||
writer.WriteEndObject();
|
||||
writer.Flush();
|
||||
outputStream.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,10 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Windows;
|
||||
using FancyZonesEditor.Models;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
@@ -18,20 +19,30 @@ namespace FancyZonesEditor
|
||||
// Other UIs in the editor will subscribe to change events on the properties to stay up to date as these properties change
|
||||
public class Settings : INotifyPropertyChanged
|
||||
{
|
||||
private readonly CanvasLayoutModel _blankCustomModel;
|
||||
private enum CmdArgs
|
||||
{
|
||||
MonitorHandle = 1,
|
||||
X_Y_Width_Height,
|
||||
ResolutionKey,
|
||||
ActiveZoneSetTmpFile,
|
||||
AppliedZoneSetTmpFile,
|
||||
CustomZoneSetsTmpFile,
|
||||
}
|
||||
|
||||
private static CanvasLayoutModel _blankCustomModel;
|
||||
private readonly CanvasLayoutModel _focusModel;
|
||||
private readonly GridLayoutModel _rowsModel;
|
||||
private readonly GridLayoutModel _columnsModel;
|
||||
private readonly GridLayoutModel _gridModel;
|
||||
private readonly GridLayoutModel _priorityGridModel;
|
||||
|
||||
private static readonly ushort _focusModelId = 0xFFFF;
|
||||
private static readonly ushort _rowsModelId = 0xFFFE;
|
||||
private static readonly ushort _columnsModelId = 0xFFFD;
|
||||
private static readonly ushort _gridModelId = 0xFFFC;
|
||||
private static readonly ushort _priorityGridModelId = 0xFFFB;
|
||||
private static readonly ushort _blankCustomModelId = 0xFFFA;
|
||||
private static readonly ushort _lastPrefinedId = _blankCustomModelId;
|
||||
public const ushort _focusModelId = 0xFFFF;
|
||||
public const ushort _rowsModelId = 0xFFFE;
|
||||
public const ushort _columnsModelId = 0xFFFD;
|
||||
public const ushort _gridModelId = 0xFFFC;
|
||||
public const ushort _priorityGridModelId = 0xFFFB;
|
||||
public const ushort _blankCustomModelId = 0xFFFA;
|
||||
public const ushort _lastPrefinedId = _blankCustomModelId;
|
||||
|
||||
// hard coded data for all the "Priority Grid" configurations that are unique to "Grid"
|
||||
private static readonly byte[][] _priorityData = new byte[][]
|
||||
@@ -73,34 +84,30 @@ namespace FancyZonesEditor
|
||||
|
||||
// Initialize the five default layout models: Focus, Columns, Rows, Grid, and PriorityGrid
|
||||
DefaultModels = new List<LayoutModel>(5);
|
||||
_focusModel = new CanvasLayoutModel("Focus", _focusModelId, (int)_workArea.Width, (int)_workArea.Height);
|
||||
_focusModel = new CanvasLayoutModel("Focus", LayoutType.Focus, (int)_workArea.Width, (int)_workArea.Height);
|
||||
DefaultModels.Add(_focusModel);
|
||||
|
||||
_columnsModel = new GridLayoutModel("Columns", _columnsModelId)
|
||||
_columnsModel = new GridLayoutModel("Columns", LayoutType.Columns)
|
||||
{
|
||||
Rows = 1,
|
||||
RowPercents = new int[1] { _multiplier },
|
||||
};
|
||||
DefaultModels.Add(_columnsModel);
|
||||
|
||||
_rowsModel = new GridLayoutModel("Rows", _rowsModelId)
|
||||
_rowsModel = new GridLayoutModel("Rows", LayoutType.Rows)
|
||||
{
|
||||
Columns = 1,
|
||||
ColumnPercents = new int[1] { _multiplier },
|
||||
};
|
||||
DefaultModels.Add(_rowsModel);
|
||||
|
||||
_gridModel = new GridLayoutModel("Grid", _gridModelId);
|
||||
_gridModel = new GridLayoutModel("Grid", LayoutType.Grid);
|
||||
DefaultModels.Add(_gridModel);
|
||||
|
||||
_priorityGridModel = new GridLayoutModel("Priority Grid", _priorityGridModelId);
|
||||
_priorityGridModel = new GridLayoutModel("Priority Grid", LayoutType.PriorityGrid);
|
||||
DefaultModels.Add(_priorityGridModel);
|
||||
|
||||
_blankCustomModel = new CanvasLayoutModel("Create new custom", _blankCustomModelId, (int)_workArea.Width, (int)_workArea.Height);
|
||||
|
||||
_zoneCount = ReadRegistryInt("ZoneCount", 3);
|
||||
_spacing = ReadRegistryInt("Spacing", 16);
|
||||
_showSpacing = ReadRegistryInt("ShowSpacing", 1) == 1;
|
||||
_blankCustomModel = new CanvasLayoutModel("Create new custom", LayoutType.Blank, (int)_workArea.Width, (int)_workArea.Height);
|
||||
|
||||
UpdateLayoutModels();
|
||||
}
|
||||
@@ -118,7 +125,6 @@ namespace FancyZonesEditor
|
||||
if (_zoneCount != value)
|
||||
{
|
||||
_zoneCount = value;
|
||||
Registry.SetValue(_uniqueRegistryPath, "ZoneCount", _zoneCount, RegistryValueKind.DWord);
|
||||
UpdateLayoutModels();
|
||||
FirePropertyChanged("ZoneCount");
|
||||
}
|
||||
@@ -140,7 +146,6 @@ namespace FancyZonesEditor
|
||||
if (_spacing != value)
|
||||
{
|
||||
_spacing = value;
|
||||
Registry.SetValue(_uniqueRegistryPath, "Spacing", _spacing, RegistryValueKind.DWord);
|
||||
FirePropertyChanged("Spacing");
|
||||
}
|
||||
}
|
||||
@@ -161,7 +166,6 @@ namespace FancyZonesEditor
|
||||
if (_showSpacing != value)
|
||||
{
|
||||
_showSpacing = value;
|
||||
Registry.SetValue(_uniqueRegistryPath, "ShowSpacing", _showSpacing, RegistryValueKind.DWord);
|
||||
FirePropertyChanged("ShowSpacing");
|
||||
}
|
||||
}
|
||||
@@ -220,18 +224,33 @@ namespace FancyZonesEditor
|
||||
|
||||
public static string UniqueKey { get; private set; }
|
||||
|
||||
private string _uniqueRegistryPath;
|
||||
public static string ActiveZoneSetUUid { get; private set; }
|
||||
|
||||
public static LayoutType ActiveZoneSetLayoutType { get; private set; }
|
||||
|
||||
public static string ActiveZoneSetTmpFile
|
||||
{
|
||||
get { return _activeZoneSetTmpFile; }
|
||||
}
|
||||
|
||||
private static string _activeZoneSetTmpFile;
|
||||
|
||||
public static string AppliedZoneSetTmpFile
|
||||
{
|
||||
get { return _appliedZoneSetTmpFile; }
|
||||
}
|
||||
|
||||
private static string _appliedZoneSetTmpFile;
|
||||
|
||||
public static string CustomZoneSetsTmpFile
|
||||
{
|
||||
get { return _customZoneSetsTmpFile; }
|
||||
}
|
||||
|
||||
private static string _customZoneSetsTmpFile;
|
||||
|
||||
public static string WorkAreaKey { get; private set; }
|
||||
|
||||
public static float Dpi { get; private set; }
|
||||
|
||||
private int ReadRegistryInt(string valueName, int defaultValue)
|
||||
{
|
||||
object obj = Registry.GetValue(_uniqueRegistryPath, valueName, defaultValue);
|
||||
return (obj != null) ? (int)obj : defaultValue;
|
||||
}
|
||||
|
||||
// UpdateLayoutModels
|
||||
// Update the five default layouts based on the new ZoneCount
|
||||
private void UpdateLayoutModels()
|
||||
@@ -327,59 +346,87 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseDeviceInfoData()
|
||||
{
|
||||
FileStream inputStream = File.Open(Settings.ActiveZoneSetTmpFile, FileMode.Open);
|
||||
var jsonObject = JsonDocument.Parse(inputStream, options: default).RootElement;
|
||||
|
||||
UniqueKey = jsonObject.GetProperty("device-id").GetString();
|
||||
ActiveZoneSetUUid = jsonObject.GetProperty("active-zoneset").GetProperty("uuid").GetString();
|
||||
string layoutType = jsonObject.GetProperty("active-zoneset").GetProperty("type").GetString();
|
||||
|
||||
if (ActiveZoneSetUUid == "null" || layoutType == "blank")
|
||||
{
|
||||
// Default selection is Focus
|
||||
ActiveZoneSetLayoutType = LayoutType.Focus;
|
||||
_showSpacing = true;
|
||||
_spacing = 16;
|
||||
_zoneCount = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (layoutType)
|
||||
{
|
||||
case "focus":
|
||||
ActiveZoneSetLayoutType = LayoutType.Focus;
|
||||
break;
|
||||
case "columns":
|
||||
ActiveZoneSetLayoutType = LayoutType.Columns;
|
||||
break;
|
||||
case "rows":
|
||||
ActiveZoneSetLayoutType = LayoutType.Rows;
|
||||
break;
|
||||
case "grid":
|
||||
ActiveZoneSetLayoutType = LayoutType.Grid;
|
||||
break;
|
||||
case "priority-grid":
|
||||
ActiveZoneSetLayoutType = LayoutType.PriorityGrid;
|
||||
break;
|
||||
case "custom":
|
||||
ActiveZoneSetLayoutType = LayoutType.Custom;
|
||||
break;
|
||||
}
|
||||
|
||||
_showSpacing = jsonObject.GetProperty("editor-show-spacing").GetBoolean();
|
||||
_spacing = jsonObject.GetProperty("editor-spacing").GetInt32();
|
||||
_zoneCount = jsonObject.GetProperty("editor-zone-count").GetInt32();
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseCommandLineArgs()
|
||||
{
|
||||
_workArea = SystemParameters.WorkArea;
|
||||
Monitor = 0;
|
||||
_uniqueRegistryPath = FullRegistryPath;
|
||||
UniqueKey = string.Empty;
|
||||
Dpi = 1;
|
||||
|
||||
string[] args = Environment.GetCommandLineArgs();
|
||||
if (args.Length == 7)
|
||||
{
|
||||
// 1 = unique key for per-monitor settings
|
||||
// 2 = layoutid used to generate current layout (used to pick the default layout to show)
|
||||
// 3 = handle to monitor (passed back to engine to persist data)
|
||||
// 4 = X_Y_Width_Height in a dpi-scaled-but-unaware coords (where EditorOverlay shows up)
|
||||
// 5 = resolution key (passed back to engine to persist data)
|
||||
// 6 = monitor DPI (float)
|
||||
UniqueKey = args[1];
|
||||
_uniqueRegistryPath += "\\" + UniqueKey;
|
||||
if (uint.TryParse(args[(int)CmdArgs.MonitorHandle], out uint monitor))
|
||||
{
|
||||
Monitor = monitor;
|
||||
}
|
||||
|
||||
var parsedLocation = args[4].Split('_');
|
||||
var parsedLocation = args[(int)CmdArgs.X_Y_Width_Height].Split('_');
|
||||
var x = int.Parse(parsedLocation[0]);
|
||||
var y = int.Parse(parsedLocation[1]);
|
||||
var width = int.Parse(parsedLocation[2]);
|
||||
var height = int.Parse(parsedLocation[3]);
|
||||
|
||||
WorkAreaKey = args[5];
|
||||
|
||||
// Try invariant culture first, caller likely uses invariant i.e. "C" locale to construct parameters
|
||||
foreach (var cultureInfo in new[] { CultureInfo.InvariantCulture, CultureInfo.CurrentCulture, CultureInfo.CurrentUICulture })
|
||||
{
|
||||
try
|
||||
{
|
||||
Dpi = float.Parse(args[6], cultureInfo);
|
||||
break;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
_workArea = new Rect(x, y, width, height);
|
||||
|
||||
if (uint.TryParse(args[4], out uint monitor))
|
||||
{
|
||||
Monitor = monitor;
|
||||
}
|
||||
WorkAreaKey = args[(int)CmdArgs.ResolutionKey];
|
||||
|
||||
_activeZoneSetTmpFile = args[(int)CmdArgs.ActiveZoneSetTmpFile];
|
||||
_appliedZoneSetTmpFile = args[(int)CmdArgs.AppliedZoneSetTmpFile];
|
||||
_customZoneSetsTmpFile = args[(int)CmdArgs.CustomZoneSetsTmpFile];
|
||||
|
||||
ParseDeviceInfoData();
|
||||
}
|
||||
}
|
||||
|
||||
public IList<LayoutModel> DefaultModels { get; }
|
||||
|
||||
public ObservableCollection<LayoutModel> CustomModels
|
||||
public static ObservableCollection<LayoutModel> CustomModels
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -393,14 +440,14 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
|
||||
private ObservableCollection<LayoutModel> _customModels;
|
||||
private static ObservableCollection<LayoutModel> _customModels;
|
||||
|
||||
public static readonly string RegistryPath = "SOFTWARE\\SuperFancyZones";
|
||||
public static readonly string FullRegistryPath = "HKEY_CURRENT_USER\\" + RegistryPath;
|
||||
|
||||
public static bool IsPredefinedLayout(LayoutModel model)
|
||||
{
|
||||
return model.Id >= _lastPrefinedId;
|
||||
return model.Type != LayoutType.Custom;
|
||||
}
|
||||
|
||||
// implementation of INotifyProeprtyChanged
|
||||
|
||||
Reference in New Issue
Block a user