[FancyZones Editor] New UX for the FZ editor. (#9325)

* Removed MetroWindow, added theming support and modernWPF

* Rmoved MahApps refs

* Removed MahApps

* Updated canvas zones

* Updated GridEditor

* Fixes

* UI updates

* New layout type selection dialog

* New editor UI

* Updates

* Fix

* UI enhancements

* Updated UI

* Added styles to layoutpreview

* Accesibility improvements

* Accesibility and styling improvements

* Fix

* Cleaned up brushes

* Updated UX

* Updated UI

* Added no layouts description

* Fix

* UI fixes

* [FZ Editor] Serialize/deserialize settings (#8615)

* conflicts fix

* [FZ Editor] Parse json file instead of command line args (#8649)

* [FZ Editor] Serialize/deserialize settings fix (#8707)

* [FZ Editor] Hide unsupported settings in custom layouts flyouts (#8716)

* [FZ Editor] Duplicate custom layouts (#8718)

* [FZ Editor] Duplicate layout behavior (#8720)

* New UX proposal

* Updated spacing

* Switching to toggleswitches

* Revert toggleswitch

* Updated colorbrush

* Updated string for saving label

* Updated UI

* Dark theme color fixes

* Removed space

* [FZ Editor] Bind dialog properties (#9199)

* Resize editor window to fit the content in single-monitor mode (#9203)

* Editor opening fix (#9207)

* Disable "Create" button if the Name textbox is empty (#9212)

* [FZ Editor] Changed edit dialog for template layouts. (#9233)

* [FZ Editor] Small fixes and refactoring. (#9236)

* new layout creation refactoring
* "Save and apply" applies the layout
* number of zones header hide

* [FZ Editor] Empty layout template. (#9237)

* [FZ Editor] Move "Duplicate" and "Delete" buttons to the Edit dialog. (#9272)

* [FZ Editor] Preview the applied layout after editing another layout. (#9278)

* Fixed "Save and apply" button behavior (#9286)

* [FZ Editor] Save template layouts in the settings. (#9283)

* Added default custom layout name (#9291)

* close dialog before opening zones editor (#9302)

* Pressing Esc closes dialogs (#9301)

* [FZ Editor] Reset applied layout to "No layout" if it was deleted. (#9315)

* [FZ Editor] Dark theme colors (#9317)

* "Number of zones" buttons colors. (#9321)

* rebase fix

* added ModernWpf.dll

* address PR comments: updated colors

* added comments, replaced magic numbers

* refactoring

* merge zones crash fix

* removed redundant using directive

Co-authored-by: Niels Laute <niels9001@hotmail.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
Seraphima Zykova
2021-01-27 21:33:52 +03:00
committed by GitHub
parent eb15cdde1b
commit 646d61bd4d
61 changed files with 3664 additions and 2781 deletions

View File

@@ -2,9 +2,7 @@
// 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.Text.Json;
using System.Windows;
namespace FancyZonesEditor.Models
@@ -14,7 +12,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; }
@@ -35,6 +33,17 @@ namespace FancyZonesEditor.Models
{
}
public CanvasLayoutModel(CanvasLayoutModel other)
: base(other)
{
CanvasRect = new Rect(other.CanvasRect.X, other.CanvasRect.Y, other.CanvasRect.Width, other.CanvasRect.Height);
foreach (Int32Rect zone in other.Zones)
{
Zones.Add(zone);
}
}
// Zones - the list of all zones in this layout, described as independent rectangles
public IList<Int32Rect> Zones { get; private set; } = new List<Int32Rect>();
@@ -54,6 +63,28 @@ namespace FancyZonesEditor.Models
UpdateLayout();
}
// InitTemplateZones
// Creates zones based on template zones count
public override void InitTemplateZones()
{
Zones.Clear();
var workingArea = App.Overlay.WorkArea;
int topLeftCoordinate = (int)App.Overlay.ScaleCoordinateWithCurrentMonitorDpi(100); // TODO: replace magic numbers
int width = (int)(workingArea.Width * 0.4);
int height = (int)(workingArea.Height * 0.4);
Int32Rect focusZoneRect = new Int32Rect(topLeftCoordinate, topLeftCoordinate, width, height);
int focusRectXIncrement = (TemplateZoneCount <= 1) ? 0 : (int)App.Overlay.ScaleCoordinateWithCurrentMonitorDpi(50); // TODO: replace magic numbers
int focusRectYIncrement = (TemplateZoneCount <= 1) ? 0 : (int)App.Overlay.ScaleCoordinateWithCurrentMonitorDpi(50); // TODO: replace magic numbers
for (int i = 0; i < TemplateZoneCount; i++)
{
Zones.Add(focusZoneRect);
focusZoneRect.X += focusRectXIncrement;
focusZoneRect.Y += focusRectYIncrement;
}
}
private void UpdateLayout()
{
FirePropertyChanged();
@@ -71,6 +102,7 @@ namespace FancyZonesEditor.Models
layout.Zones.Add(zone);
}
layout.SensitivityRadius = SensitivityRadius;
return layout;
}
@@ -81,37 +113,8 @@ namespace FancyZonesEditor.Models
{
other.Zones.Add(zone);
}
}
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; }
other.SensitivityRadius = SensitivityRadius;
}
// PersistData
@@ -119,48 +122,6 @@ namespace FancyZonesEditor.Models
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<JsonElement>(jsonString));
SerializeCreatedCustomZonesets();
}
}
}

View File

@@ -1,11 +1,8 @@
// 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.Text.Json;
using System.Windows;
namespace FancyZonesEditor.Models
{
@@ -14,7 +11,25 @@ namespace FancyZonesEditor.Models
public class GridLayoutModel : LayoutModel
{
// Non-localizable strings
private const string ModelTypeID = "grid";
public const string ModelTypeID = "grid";
public const int GridMultiplier = 10000;
// hard coded data for all the "Priority Grid" configurations that are unique to "Grid"
private static readonly byte[][] _priorityData = new byte[][]
{
new byte[] { 0, 0, 0, 0, 0, 1, 1, 39, 16, 39, 16, 0 },
new byte[] { 0, 0, 0, 0, 0, 1, 2, 39, 16, 26, 11, 13, 5, 0, 1 },
new byte[] { 0, 0, 0, 0, 0, 1, 3, 39, 16, 9, 196, 19, 136, 9, 196, 0, 1, 2 },
new byte[] { 0, 0, 0, 0, 0, 2, 3, 19, 136, 19, 136, 9, 196, 19, 136, 9, 196, 0, 1, 2, 0, 1, 3 },
new byte[] { 0, 0, 0, 0, 0, 2, 3, 19, 136, 19, 136, 9, 196, 19, 136, 9, 196, 0, 1, 2, 3, 1, 4 },
new byte[] { 0, 0, 0, 0, 0, 3, 3, 13, 5, 13, 6, 13, 5, 9, 196, 19, 136, 9, 196, 0, 1, 2, 0, 1, 3, 4, 1, 5 },
new byte[] { 0, 0, 0, 0, 0, 3, 3, 13, 5, 13, 6, 13, 5, 9, 196, 19, 136, 9, 196, 0, 1, 2, 3, 1, 4, 5, 1, 6 },
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 2, 5, 6, 1, 2, 7 },
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 2, 5, 6, 1, 7, 8 },
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 5, 6, 7, 1, 8, 9 },
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 5, 6, 7, 8, 9, 10 },
};
// Rows - number of rows in the Grid
public int Rows
@@ -29,7 +44,6 @@ namespace FancyZonesEditor.Models
if (_rows != value)
{
_rows = value;
FirePropertyChanged();
}
}
}
@@ -49,7 +63,6 @@ namespace FancyZonesEditor.Models
if (_cols != value)
{
_cols = value;
FirePropertyChanged();
}
}
}
@@ -62,10 +75,50 @@ namespace FancyZonesEditor.Models
public int[,] CellChildMap { get; set; }
// RowPercents - represents the %age height of each row in the grid
public List<int> RowPercents { get; set; }
public List<int> RowPercents { get; set; } = new List<int>();
// ColumnPercents - represents the %age width of each column in the grid
public List<int> ColumnPercents { get; set; }
public List<int> ColumnPercents { get; set; } = new List<int>();
// ShowSpacing - flag if free space between cells should be presented
public bool ShowSpacing
{
get
{
return _showSpacing;
}
set
{
if (value != _showSpacing)
{
_showSpacing = value;
FirePropertyChanged(nameof(ShowSpacing));
}
}
}
private bool _showSpacing = LayoutSettings.DefaultShowSpacing;
// Spacing - free space between cells
public int Spacing
{
get
{
return _spacing;
}
set
{
if (value != _spacing)
{
_spacing = value;
FirePropertyChanged(nameof(Spacing));
}
}
}
private int _spacing = LayoutSettings.DefaultSpacing;
// FreeZones (not persisted) - used to keep track of child indices that are no longer in use in the CellChildMap,
// making them candidates for re-use when it's needed to add another child
@@ -97,13 +150,46 @@ namespace FancyZonesEditor.Models
CellChildMap = cellChildMap;
}
public GridLayoutModel(GridLayoutModel other)
: base(other)
{
_rows = other._rows;
_cols = other._cols;
_showSpacing = other._showSpacing;
_spacing = other._spacing;
CellChildMap = new int[_rows, _cols];
for (int row = 0; row < _rows; row++)
{
for (int col = 0; col < _cols; col++)
{
CellChildMap[row, col] = other.CellChildMap[row, col];
}
}
for (int row = 0; row < _rows; row++)
{
RowPercents.Add(other.RowPercents[row]);
}
for (int col = 0; col < _cols; col++)
{
ColumnPercents.Add(other.ColumnPercents[col]);
}
}
public void UpdatePreview()
{
FirePropertyChanged();
}
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++];
_rows = data[i++];
_cols = data[i++];
RowPercents = new List<int>(Rows);
for (int row = 0; row < Rows; row++)
@@ -125,6 +211,8 @@ namespace FancyZonesEditor.Models
CellChildMap[row, col] = data[i++];
}
}
FirePropertyChanged();
}
// Clone
@@ -171,30 +259,36 @@ namespace FancyZonesEditor.Models
}
layout.ColumnPercents = colPercents;
layout.ShowSpacing = ShowSpacing;
layout.Spacing = Spacing;
layout.SensitivityRadius = SensitivityRadius;
}
private struct GridLayoutInfo
// InitTemplateZones
// Creates zones based on template zones count
public override void InitTemplateZones()
{
public int Rows { get; set; }
switch (Type)
{
case LayoutType.Rows:
InitRows();
break;
case LayoutType.Columns:
InitColumns();
break;
case LayoutType.Grid:
InitGrid();
break;
case LayoutType.PriorityGrid:
InitPriorityGrid();
break;
case LayoutType.Custom:
InitColumns(); // Custom is initialized with columns
break;
}
public int Columns { get; set; }
public List<int> RowsPercentage { get; set; }
public List<int> 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; }
FirePropertyChanged();
}
// PersistData
@@ -202,40 +296,105 @@ namespace FancyZonesEditor.Models
protected override void PersistData()
{
AddCustomLayout(this);
}
GridLayoutInfo layoutInfo = new GridLayoutInfo
{
Rows = Rows,
Columns = Columns,
RowsPercentage = RowPercents,
ColumnsPercentage = ColumnPercents,
CellChildMap = new int[Rows][],
};
private void InitRows()
{
CellChildMap = new int[TemplateZoneCount, 1];
RowPercents = new List<int>(TemplateZoneCount);
for (int row = 0; row < Rows; row++)
for (int i = 0; i < TemplateZoneCount; i++)
{
layoutInfo.CellChildMap[row] = new int[Columns];
for (int col = 0; col < Columns; col++)
CellChildMap[i, 0] = i;
// Note: This is NOT equal to _multiplier / ZoneCount and is done like this to make
// the sum of all RowPercents exactly (_multiplier).
RowPercents.Add(((GridMultiplier * (i + 1)) / TemplateZoneCount) - ((GridMultiplier * i) / TemplateZoneCount));
}
_rows = TemplateZoneCount;
}
private void InitColumns()
{
CellChildMap = new int[1, TemplateZoneCount];
ColumnPercents = new List<int>(TemplateZoneCount);
for (int i = 0; i < TemplateZoneCount; i++)
{
CellChildMap[0, i] = i;
// Note: This is NOT equal to _multiplier / ZoneCount and is done like this to make
// the sum of all RowPercents exactly (_multiplier).
ColumnPercents.Add(((GridMultiplier * (i + 1)) / TemplateZoneCount) - ((GridMultiplier * i) / TemplateZoneCount));
}
_cols = TemplateZoneCount;
}
private void InitGrid()
{
int rows = 1;
while (TemplateZoneCount / rows >= rows)
{
rows++;
}
rows--;
int cols = TemplateZoneCount / rows;
if (TemplateZoneCount % rows == 0)
{
// even grid
}
else
{
cols++;
}
RowPercents = new List<int>(rows);
ColumnPercents = new List<int>(cols);
CellChildMap = new int[rows, cols];
// Note: The following are NOT equal to _multiplier divided by rows or columns and is
// done like this to make the sum of all RowPercents exactly (_multiplier).
for (int row = 0; row < rows; row++)
{
RowPercents.Add(((GridMultiplier * (row + 1)) / rows) - ((GridMultiplier * row) / rows));
}
for (int col = 0; col < cols; col++)
{
ColumnPercents.Add(((GridMultiplier * (col + 1)) / cols) - ((GridMultiplier * col) / cols));
}
int index = 0;
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
layoutInfo.CellChildMap[row][col] = CellChildMap[row, col];
CellChildMap[row, col] = index++;
if (index == TemplateZoneCount)
{
index--;
}
}
}
GridLayoutJson jsonObj = new GridLayoutJson
{
Uuid = Uuid,
Name = Name,
Type = ModelTypeID,
Info = layoutInfo,
};
JsonSerializerOptions options = new JsonSerializerOptions
{
PropertyNamingPolicy = new DashCaseNamingPolicy(),
};
_rows = rows;
_cols = cols;
}
string jsonString = JsonSerializer.Serialize(jsonObj, options);
AddCustomLayoutJson(JsonSerializer.Deserialize<JsonElement>(jsonString));
SerializeCreatedCustomZonesets();
private void InitPriorityGrid()
{
if (TemplateZoneCount <= _priorityData.Length)
{
Reload(_priorityData[TemplateZoneCount - 1]);
}
else
{
// same as grid;
InitGrid();
}
}
}
}

View File

@@ -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
{
@@ -42,6 +39,17 @@ namespace FancyZonesEditor.Models
Type = type;
}
protected LayoutModel(LayoutModel other)
{
_guid = other._guid;
_name = other._name;
Type = other.Type;
_isSelected = other._isSelected;
_isApplied = other._isApplied;
_sensitivityRadius = other._sensitivityRadius;
_zoneCount = other._zoneCount;
}
// Name - the display name for this layout model - is also used as the key in the registry
public string Name
{
@@ -55,7 +63,7 @@ namespace FancyZonesEditor.Models
if (_name != value)
{
_name = value;
FirePropertyChanged();
FirePropertyChanged(nameof(Name));
}
}
}
@@ -82,6 +90,14 @@ namespace FancyZonesEditor.Models
}
}
public bool IsCustom
{
get
{
return Type == LayoutType.Custom;
}
}
// 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
public bool IsSelected
@@ -96,13 +112,14 @@ namespace FancyZonesEditor.Models
if (_isSelected != value)
{
_isSelected = value;
FirePropertyChanged();
FirePropertyChanged(nameof(IsSelected));
}
}
}
private bool _isSelected;
// IsApplied (not-persisted) - tracks whether or not this LayoutModel is applied in the picker
public bool IsApplied
{
get
@@ -115,13 +132,53 @@ namespace FancyZonesEditor.Models
if (_isApplied != value)
{
_isApplied = value;
FirePropertyChanged();
FirePropertyChanged(nameof(IsApplied));
}
}
}
private bool _isApplied;
public int SensitivityRadius
{
get
{
return _sensitivityRadius;
}
set
{
if (value != _sensitivityRadius)
{
_sensitivityRadius = value;
FirePropertyChanged(nameof(SensitivityRadius));
}
}
}
private int _sensitivityRadius = LayoutSettings.DefaultSensitivityRadius;
// TemplateZoneCount - number of zones selected in the picker window for template layouts
public int TemplateZoneCount
{
get
{
return _zoneCount;
}
set
{
if (value != _zoneCount)
{
_zoneCount = value;
InitTemplateZones();
FirePropertyChanged(nameof(TemplateZoneCount));
}
}
}
private int _zoneCount = LayoutSettings.DefaultZoneCount;
// implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
@@ -134,11 +191,11 @@ namespace FancyZonesEditor.Models
// 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,48 +203,25 @@ namespace FancyZonesEditor.Models
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<LayoutModel> LoadCustomModels()
{
_customModels = new ObservableCollection<LayoutModel>();
App.FancyZonesEditorIO.ParseLayouts(ref _customModels, ref _deletedCustomModels);
return _customModels;
}
private static ObservableCollection<LayoutModel> _customModels;
private static List<string> _deletedCustomModels = new List<string>();
private static List<JsonElement> _createdCustomLayouts = new List<JsonElement>();
// InitTemplateZones
// Creates zones based on template zones count
public abstract void InitTemplateZones();
// Callbacks that the base LayoutModel makes to derived types
protected abstract void PersistData();
@@ -197,21 +231,6 @@ namespace FancyZonesEditor.Models
public void Persist()
{
PersistData();
Apply();
}
public void Apply()
{
MainWindowSettingsModel settings = ((App)App.Current).MainWindowSettings;
settings.ResetAppliedModel();
IsApplied = true;
// update settings
App.Overlay.CurrentLayoutSettings.ZonesetUuid = Uuid;
App.Overlay.CurrentLayoutSettings.Type = Type;
// update temp file
App.FancyZonesEditorIO.SerializeAppliedLayouts();
}
}
}

View File

@@ -9,13 +9,16 @@ namespace FancyZonesEditor
{
public class LayoutSettings
{
public static bool DefaultShowSpacing => true;
// TODO: share the constants b/w C# Editor and FancyZoneLib
public const bool DefaultShowSpacing = true;
public static int DefaultSpacing => 16;
public const int DefaultSpacing = 16;
public static int DefaultZoneCount => 3;
public const int DefaultZoneCount = 3;
public static int DefaultSensitivityRadius => 20;
public const int DefaultSensitivityRadius = 20;
public const int MaxZones = 40;
public string ZonesetUuid { get; set; } = string.Empty;

View File

@@ -2,12 +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.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using FancyZonesEditor.Models;
namespace FancyZonesEditor
@@ -25,43 +23,17 @@ namespace FancyZonesEditor
VirtualDesktopId,
}
private static CanvasLayoutModel _blankCustomModel;
private readonly CanvasLayoutModel _blankModel;
private readonly CanvasLayoutModel _focusModel;
private readonly GridLayoutModel _rowsModel;
private readonly GridLayoutModel _columnsModel;
private readonly GridLayoutModel _gridModel;
private readonly GridLayoutModel _priorityGridModel;
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 _lastDefinedId = _blankCustomModelId;
// Non-localizable strings
public static readonly string RegistryPath = "SOFTWARE\\SuperFancyZones";
public static readonly string FullRegistryPath = "HKEY_CURRENT_USER\\" + RegistryPath;
// hard coded data for all the "Priority Grid" configurations that are unique to "Grid"
private static readonly byte[][] _priorityData = new byte[][]
{
new byte[] { 0, 0, 0, 0, 0, 1, 1, 39, 16, 39, 16, 0 },
new byte[] { 0, 0, 0, 0, 0, 1, 2, 39, 16, 26, 11, 13, 5, 0, 1 },
new byte[] { 0, 0, 0, 0, 0, 1, 3, 39, 16, 9, 196, 19, 136, 9, 196, 0, 1, 2 },
new byte[] { 0, 0, 0, 0, 0, 2, 3, 19, 136, 19, 136, 9, 196, 19, 136, 9, 196, 0, 1, 2, 0, 1, 3 },
new byte[] { 0, 0, 0, 0, 0, 2, 3, 19, 136, 19, 136, 9, 196, 19, 136, 9, 196, 0, 1, 2, 3, 1, 4 },
new byte[] { 0, 0, 0, 0, 0, 3, 3, 13, 5, 13, 6, 13, 5, 9, 196, 19, 136, 9, 196, 0, 1, 2, 0, 1, 3, 4, 1, 5 },
new byte[] { 0, 0, 0, 0, 0, 3, 3, 13, 5, 13, 6, 13, 5, 9, 196, 19, 136, 9, 196, 0, 1, 2, 3, 1, 4, 5, 1, 6 },
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 2, 5, 6, 1, 2, 7 },
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 2, 5, 6, 1, 7, 8 },
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 5, 6, 7, 1, 8, 9 },
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 5, 6, 7, 8, 9, 10 },
};
private const int _multiplier = 10000;
public bool IsCustomLayoutActive
{
get
@@ -80,112 +52,41 @@ namespace FancyZonesEditor
public MainWindowSettingsModel()
{
// Initialize the five default layout models: Focus, Columns, Rows, Grid, and PriorityGrid
DefaultModels = new List<LayoutModel>(5);
// Initialize default layout models: Blank, Focus, Columns, Rows, Grid, and PriorityGrid
_blankModel = new CanvasLayoutModel(Properties.Resources.Template_Layout_Blank, LayoutType.Blank)
{
TemplateZoneCount = 0,
SensitivityRadius = 0,
};
DefaultModels.Add(_blankModel);
_focusModel = new CanvasLayoutModel(Properties.Resources.Template_Layout_Focus, LayoutType.Focus);
_focusModel.InitTemplateZones();
DefaultModels.Add(_focusModel);
_columnsModel = new GridLayoutModel(Properties.Resources.Template_Layout_Columns, LayoutType.Columns)
{
Rows = 1,
RowPercents = new List<int>(1) { _multiplier },
RowPercents = new List<int>(1) { GridLayoutModel.GridMultiplier },
};
_columnsModel.InitTemplateZones();
DefaultModels.Add(_columnsModel);
_rowsModel = new GridLayoutModel(Properties.Resources.Template_Layout_Rows, LayoutType.Rows)
{
Columns = 1,
ColumnPercents = new List<int>(1) { _multiplier },
ColumnPercents = new List<int>(1) { GridLayoutModel.GridMultiplier },
};
_rowsModel.InitTemplateZones();
DefaultModels.Add(_rowsModel);
_gridModel = new GridLayoutModel(Properties.Resources.Template_Layout_Grid, LayoutType.Grid);
_gridModel.InitTemplateZones();
DefaultModels.Add(_gridModel);
_priorityGridModel = new GridLayoutModel(Properties.Resources.Template_Layout_Priority_Grid, LayoutType.PriorityGrid);
_priorityGridModel.InitTemplateZones();
DefaultModels.Add(_priorityGridModel);
_blankCustomModel = new CanvasLayoutModel(Properties.Resources.Custom_Layout_Create_New, LayoutType.Blank);
UpdateTemplateLayoutModels();
}
// ZoneCount - number of zones selected in the picker window
public int ZoneCount
{
get
{
return App.Overlay.CurrentLayoutSettings.ZoneCount;
}
set
{
if (App.Overlay.CurrentLayoutSettings.ZoneCount != value)
{
App.Overlay.CurrentLayoutSettings.ZoneCount = value;
UpdateTemplateLayoutModels();
FirePropertyChanged(nameof(ZoneCount));
}
}
}
// Spacing - how much space in between zones of the grid do you want
public int Spacing
{
get
{
return App.Overlay.CurrentLayoutSettings.Spacing;
}
set
{
value = Math.Max(0, value);
if (App.Overlay.CurrentLayoutSettings.Spacing != value)
{
App.Overlay.CurrentLayoutSettings.Spacing = value;
UpdateTemplateLayoutModels();
FirePropertyChanged(nameof(Spacing));
}
}
}
// ShowSpacing - is the Spacing value used or ignored?
public bool ShowSpacing
{
get
{
return App.Overlay.CurrentLayoutSettings.ShowSpacing;
}
set
{
if (App.Overlay.CurrentLayoutSettings.ShowSpacing != value)
{
App.Overlay.CurrentLayoutSettings.ShowSpacing = value;
UpdateTemplateLayoutModels();
FirePropertyChanged(nameof(ShowSpacing));
}
}
}
// SensitivityRadius - how much space inside the zone to highlight the adjacent zone too
public int SensitivityRadius
{
get
{
return App.Overlay.CurrentLayoutSettings.SensitivityRadius;
}
set
{
value = Math.Max(0, value);
if (App.Overlay.CurrentLayoutSettings.SensitivityRadius != value)
{
App.Overlay.CurrentLayoutSettings.SensitivityRadius = value;
UpdateTemplateLayoutModels();
FirePropertyChanged(nameof(SensitivityRadius));
}
}
}
// IsShiftKeyPressed - is the shift key currently being held down
@@ -228,138 +129,7 @@ namespace FancyZonesEditor
private bool _isCtrlKeyPressed;
// UpdateLayoutModels
// Update the five default layouts based on the new ZoneCount
private void UpdateTemplateLayoutModels()
{
// Update the "Focus" Default Layout
_focusModel.Zones.Clear();
// Sanity check for imported settings that may have invalid data
if (ZoneCount < 1)
{
ZoneCount = 3;
}
// If changing focus layout zones size and/or increment,
// same change should be applied in ZoneSet.cpp (ZoneSet::CalculateFocusLayout)
var workingArea = App.Overlay.WorkArea;
int topLeftCoordinate = (int)App.Overlay.ScaleCoordinateWithCurrentMonitorDpi(100); // TODO: replace magic numbers
int width = (int)(workingArea.Width * 0.4);
int height = (int)(workingArea.Height * 0.4);
Int32Rect focusZoneRect = new Int32Rect(topLeftCoordinate, topLeftCoordinate, width, height);
int focusRectXIncrement = (ZoneCount <= 1) ? 0 : (int)App.Overlay.ScaleCoordinateWithCurrentMonitorDpi(50);
int focusRectYIncrement = (ZoneCount <= 1) ? 0 : (int)App.Overlay.ScaleCoordinateWithCurrentMonitorDpi(50);
for (int i = 0; i < ZoneCount; i++)
{
_focusModel.Zones.Add(focusZoneRect);
focusZoneRect.X += focusRectXIncrement;
focusZoneRect.Y += focusRectYIncrement;
}
// Update the "Rows" and "Columns" Default Layouts
// They can share their model, just transposed
_rowsModel.CellChildMap = new int[ZoneCount, 1];
_columnsModel.CellChildMap = new int[1, ZoneCount];
_rowsModel.Rows = _columnsModel.Columns = ZoneCount;
_rowsModel.RowPercents = _columnsModel.ColumnPercents = new List<int>(ZoneCount);
for (int i = 0; i < ZoneCount; i++)
{
_rowsModel.CellChildMap[i, 0] = i;
_columnsModel.CellChildMap[0, i] = i;
// Note: This is NOT equal to _multiplier / ZoneCount and is done like this to make
// the sum of all RowPercents exactly (_multiplier).
// _columnsModel is sharing the same array
_rowsModel.RowPercents.Add(((_multiplier * (i + 1)) / ZoneCount) - ((_multiplier * i) / ZoneCount));
}
// Update the "Grid" Default Layout
int rows = 1;
while (ZoneCount / rows >= rows)
{
rows++;
}
rows--;
int cols = ZoneCount / rows;
if (ZoneCount % rows == 0)
{
// even grid
}
else
{
cols++;
}
_gridModel.Rows = rows;
_gridModel.Columns = cols;
_gridModel.RowPercents = new List<int>(rows);
_gridModel.ColumnPercents = new List<int>(cols);
_gridModel.CellChildMap = new int[rows, cols];
// Note: The following are NOT equal to _multiplier divided by rows or columns and is
// done like this to make the sum of all RowPercents exactly (_multiplier).
for (int row = 0; row < rows; row++)
{
_gridModel.RowPercents.Add(((_multiplier * (row + 1)) / rows) - ((_multiplier * row) / rows));
}
for (int col = 0; col < cols; col++)
{
_gridModel.ColumnPercents.Add(((_multiplier * (col + 1)) / cols) - ((_multiplier * col) / cols));
}
int index = 0;
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
_gridModel.CellChildMap[row, col] = index++;
if (index == ZoneCount)
{
index--;
}
}
}
// Update the "Priority Grid" Default Layout
if (ZoneCount <= _priorityData.Length)
{
_priorityGridModel.Reload(_priorityData[ZoneCount - 1]);
}
else
{
// same as grid;
_priorityGridModel.Rows = _gridModel.Rows;
_priorityGridModel.Columns = _gridModel.Columns;
_priorityGridModel.RowPercents = _gridModel.RowPercents;
_priorityGridModel.ColumnPercents = _gridModel.ColumnPercents;
_priorityGridModel.CellChildMap = _gridModel.CellChildMap;
}
}
public IList<LayoutModel> DefaultModels { get; }
public static ObservableCollection<LayoutModel> CustomModels
{
get
{
if (_customModels == null)
{
_customModels = LayoutModel.LoadCustomModels();
_customModels.Insert(0, _blankCustomModel);
}
return _customModels;
}
}
private static ObservableCollection<LayoutModel> _customModels;
public CanvasLayoutModel BlankModel
public LayoutModel BlankModel
{
get
{
@@ -367,7 +137,55 @@ namespace FancyZonesEditor
}
}
private CanvasLayoutModel _blankModel = new CanvasLayoutModel(string.Empty, LayoutType.Blank);
public static IList<LayoutModel> DefaultModels { get; } = new List<LayoutModel>(6);
public static ObservableCollection<LayoutModel> CustomModels
{
get
{
return _customModels;
}
}
private static ObservableCollection<LayoutModel> _customModels = new ObservableCollection<LayoutModel>();
public LayoutModel SelectedModel
{
get
{
return _selectedModel;
}
private set
{
if (_selectedModel != value)
{
_selectedModel = value;
FirePropertyChanged(nameof(SelectedModel));
}
}
}
private LayoutModel _selectedModel = null;
public LayoutModel AppliedModel
{
get
{
return _appliedModel;
}
private set
{
if (_appliedModel != value)
{
_appliedModel = value;
FirePropertyChanged(nameof(AppliedModel));
}
}
}
private LayoutModel _appliedModel = null;
public static bool IsPredefinedLayout(LayoutModel model)
{
@@ -376,21 +194,13 @@ namespace FancyZonesEditor
public LayoutModel UpdateSelectedLayoutModel()
{
UpdateTemplateLayoutModels();
ResetAppliedModel();
ResetSelectedModel();
LayoutModel foundModel = null;
LayoutSettings currentApplied = App.Overlay.CurrentLayoutSettings;
// set new layout
if (currentApplied.Type == LayoutType.Blank)
if (currentApplied.Type == LayoutType.Custom)
{
foundModel = BlankModel;
}
else if (currentApplied.Type == LayoutType.Custom)
{
foreach (LayoutModel model in MainWindowSettingsModel.CustomModels)
foreach (LayoutModel model in CustomModels)
{
if ("{" + model.Guid.ToString().ToUpperInvariant() + "}" == currentApplied.ZonesetUuid.ToUpperInvariant())
{
@@ -408,6 +218,15 @@ namespace FancyZonesEditor
{
// found match
foundModel = model;
foundModel.TemplateZoneCount = currentApplied.ZoneCount;
foundModel.SensitivityRadius = currentApplied.SensitivityRadius;
if (foundModel is GridLayoutModel grid)
{
grid.ShowSpacing = currentApplied.ShowSpacing;
grid.Spacing = currentApplied.Spacing;
}
foundModel.InitTemplateZones();
break;
}
}
@@ -415,80 +234,74 @@ namespace FancyZonesEditor
if (foundModel == null)
{
foundModel = DefaultModels[4]; // PriorityGrid
foundModel = _priorityGridModel;
}
foundModel.IsSelected = true;
foundModel.IsApplied = true;
SetSelectedModel(foundModel);
SetAppliedModel(foundModel);
FirePropertyChanged(nameof(IsCustomLayoutActive));
return foundModel;
}
public void ResetSelectedModel()
public void RestoreSelectedModel(LayoutModel model)
{
foreach (LayoutModel model in CustomModels)
if (SelectedModel == null || model == null)
{
if (model.IsSelected)
{
model.IsSelected = false;
break;
}
return;
}
foreach (LayoutModel model in DefaultModels)
SelectedModel.SensitivityRadius = model.SensitivityRadius;
SelectedModel.TemplateZoneCount = model.TemplateZoneCount;
SelectedModel.IsSelected = model.IsSelected;
SelectedModel.IsApplied = model.IsApplied;
SelectedModel.Name = model.Name;
if (model is GridLayoutModel grid)
{
if (model.IsSelected)
{
model.IsSelected = false;
break;
}
((GridLayoutModel)SelectedModel).Spacing = grid.Spacing;
((GridLayoutModel)SelectedModel).ShowSpacing = grid.ShowSpacing;
}
}
public void ResetAppliedModel()
public void SetSelectedModel(LayoutModel model)
{
foreach (LayoutModel model in CustomModels)
if (_selectedModel != null)
{
if (model.IsApplied)
{
model.IsApplied = false;
break;
}
_selectedModel.IsSelected = false;
}
foreach (LayoutModel model in DefaultModels)
if (model != null)
{
if (model.IsApplied)
{
model.IsApplied = false;
break;
}
model.IsSelected = true;
}
SelectedModel = model;
}
public void UpdateDesktopDependantProperties(LayoutSettings prevSettings)
public void SetAppliedModel(LayoutModel model)
{
UpdateTemplateLayoutModels();
if (prevSettings.ZoneCount != ZoneCount)
if (_appliedModel != null)
{
FirePropertyChanged(nameof(ZoneCount));
_appliedModel.IsApplied = false;
}
if (prevSettings.Spacing != Spacing)
if (model != null)
{
FirePropertyChanged(nameof(Spacing));
model.IsApplied = true;
}
if (prevSettings.ShowSpacing != ShowSpacing)
{
FirePropertyChanged(nameof(ShowSpacing));
}
AppliedModel = model;
}
if (prevSettings.SensitivityRadius != SensitivityRadius)
public void UpdateDefaultModels()
{
foreach (LayoutModel model in DefaultModels)
{
FirePropertyChanged(nameof(SensitivityRadius));
if (App.Overlay.CurrentLayoutSettings.Type == model.Type && App.Overlay.CurrentLayoutSettings.ZoneCount != model.TemplateZoneCount)
{
model.TemplateZoneCount = App.Overlay.CurrentLayoutSettings.ZoneCount;
model.InitTemplateZones();
}
}
}

View File

@@ -5,7 +5,6 @@
using System;
using System.Reflection;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using FancyZonesEditor.Utils;