FancyZones and Shortcut Guide initial commit

Co-authored-by: Alexis Campailla <alexis@janeasystems.com>
Co-authored-by: Bret Anderson <bretan@microsoft.com>
Co-authored-by: Enrico Giordani <enrico.giordani@gmail.com>
Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
Co-authored-by: Jeff Bogdan <jeffbog@microsoft.com>
Co-authored-by: March Rogers <marchr@microsoft.com>
Co-authored-by: Mike Harsh <mharsh@microsoft.com>
Co-authored-by: Nachum Bundak <Nachum.Bundak@microsoft.com>
Co-authored-by: Oliver Jones <ojones@microsoft.com>
Co-authored-by: Patrick Little <plittle@microsoft.com>
This commit is contained in:
Bartosz Sosnowski
2019-09-04 18:26:26 +02:00
committed by Bartosz Sosnowski
parent 10c5396099
commit 8431b80e48
341 changed files with 54766 additions and 62 deletions

View File

@@ -0,0 +1,164 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Converters;
using System.Windows.Documents;
namespace FancyZonesEditor.Models
{
// CanvasLayoutModel
// Free form Layout Model, which specifies independent zone rects
public class CanvasLayoutModel : LayoutModel
{
public CanvasLayoutModel(ushort version, string name, ushort id, byte[] data) : base(name, id)
{
if (version == c_latestVersion)
{
Load(data);
}
}
public CanvasLayoutModel(string name, ushort id, int referenceWidth, int referenceHeight) : base(name, id)
{
// 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
{
get { return _referenceWidth; }
set
{
if (_referenceWidth != value)
{
_referenceWidth = value;
FirePropertyChanged("ReferenceWidth");
}
}
}
private int _referenceWidth;
// ReferenceHeight - the reference height for the layout rect that all Zones are relative to
public int ReferenceHeight
{
get { return _referenceHeight; }
set
{
if (_referenceHeight != value)
{
_referenceHeight = value;
FirePropertyChanged("ReferenceHeight");
}
}
}
private int _referenceHeight;
// Zones - the list of all zones in this layout, described as independent rectangles
public IList<Int32Rect> Zones { get { return _zones; } }
private IList<Int32Rect> _zones = new List<Int32Rect>();
// RemoveZoneAt
// Removes the specified index from the Zones list, and fires a property changed notification for the Zones property
public void RemoveZoneAt(int index)
{
Zones.RemoveAt(index);
FirePropertyChanged("Zones");
}
// AddZone
// Adds the specified Zone to the end of the Zones list, and fires a property changed notification for the Zones property
public void AddZone(Int32Rect zone)
{
Zones.Add(zone);
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
public override LayoutModel Clone()
{
CanvasLayoutModel layout = new CanvasLayoutModel(Name);
layout.ReferenceHeight = ReferenceHeight;
layout.ReferenceWidth = ReferenceWidth;
foreach(Int32Rect zone in Zones)
{
layout.Zones.Add(zone);
}
return layout;
}
// GetPersistData
// Implements the LayoutModel.GetPersistData abstract method
// Returns the state of this GridLayoutModel in persisted format
protected override byte[] GetPersistData()
{
byte[] data = new byte[10 + (_zones.Count * 8)];
int i = 0;
// Common persisted values between all layout types
data[i++] = (byte)(c_latestVersion / 256);
data[i++] = (byte)(c_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)
{
data[i++] = (byte)(rect.X / 256);
data[i++] = (byte)(rect.X % 256);
data[i++] = (byte)(rect.Y / 256);
data[i++] = (byte)(rect.Y % 256);
data[i++] = (byte)(rect.Width / 256);
data[i++] = (byte)(rect.Width % 256);
data[i++] = (byte)(rect.Height / 256);
data[i++] = (byte)(rect.Height % 256);
}
return data;
}
private static ushort c_latestVersion = 0;
}
}

View File

@@ -0,0 +1,224 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Documents;
namespace FancyZonesEditor.Models
{
// GridLayoutModel
// Grid-styled Layout Model, which specifies rows, columns, percentage sizes, and row/column spans
public class GridLayoutModel : LayoutModel
{
public GridLayoutModel() : 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 == c_latestVersion)
{
Reload(data);
}
}
// Rows - number of rows in the Grid
public int Rows
{
get { return _rows; }
set
{
if (_rows != value)
{
_rows = value;
FirePropertyChanged("Rows");
}
}
}
private int _rows = 1;
// Columns - number of columns in the Grid
public int Columns
{
get { return _cols; }
set
{
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
public int[,] CellChildMap { get { return _cellChildMap; } set { _cellChildMap = value; } }
private int[,] _cellChildMap;
// RowPercents - represents the %age height of each row in the grid
public int[] RowPercents { get { return _rowPercents; } set { _rowPercents = value; } }
private int[] _rowPercents;
// ColumnPercents - represents the %age width of each column in the grid
public int[] ColumnPercents { get { return _colPercents; } set { _colPercents = value; } }
private int[] _colPercents;
// 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
// TODO: do I need FreeZones on the data model? - I think I do
public IList<int> FreeZones { get { return _freeZones; } }
private IList<int> _freeZones = new List<int>();
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++];
}
_colPercents = new int[Columns];
for (int col = 0; col < Columns; col++)
{
_colPercents[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;
// Common persisted values between all layout types
data[i++] = (byte)(c_latestVersion / 256);
data[i++] = (byte)(c_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 = _colPercents[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;
}
private static ushort c_latestVersion = 0;
}
}

View File

@@ -0,0 +1,226 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32;
namespace FancyZonesEditor.Models
{
// Base LayoutModel
// Manages common properties and base persistence
public abstract class LayoutModel : INotifyPropertyChanged
{
protected LayoutModel() { }
protected LayoutModel(string name) : this()
{
Name = name;
}
protected LayoutModel(string name, ushort id) : this(name)
{
_id = id;
}
// Name - the display name for this layout model - is also used as the key in the registry
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
FirePropertyChanged("Name");
}
}
}
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
{
get
{
if (_id == 0)
{
_id = ++s_maxId;
}
return _id;
}
}
private ushort _id = 0;
// 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
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
_isSelected = value;
FirePropertyChanged("IsSelected");
}
}
}
private bool _isSelected;
// implementation of INotifyProeprtyChanged
public event PropertyChangedEventHandler PropertyChanged;
// FirePropertyChanged -- wrapper that calls INPC.PropertyChanged
protected virtual void FirePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
// Removes this Layout from the registry and the loaded CustomModels list
public void Delete()
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(c_registryPath, true);
if (key != null)
{
key.DeleteValue(Name);
}
int i = s_customModels.IndexOf(this);
if (i != -1)
{
s_customModels.RemoveAt(i);
}
}
// Loads all the Layouts persisted under the Layouts key in the registry
public static ObservableCollection<LayoutModel> LoadCustomModels()
{
s_customModels = new ObservableCollection<LayoutModel>();
RegistryKey key = Registry.CurrentUser.OpenSubKey(c_registryPath);
if (key != null)
{
foreach (string name in key.GetValueNames())
{
LayoutModel model = null;
byte[] data = (byte[])Registry.GetValue(c_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)
{
case 0: model = new GridLayoutModel(version, name, id, data); break;
case 1: model = new CanvasLayoutModel(version, name, id, data); break;
}
if (model != null)
{
if (s_maxId < id)
{
s_maxId = id;
}
s_customModels.Add(model);
}
}
}
return s_customModels;
}
private static ObservableCollection<LayoutModel> s_customModels = null;
private static ushort s_maxId = 0;
// Callbacks that the base LayoutModel makes to derived types
protected abstract byte[] GetPersistData();
public abstract LayoutModel Clone();
// PInvokes to handshake with fancyzones backend
internal static class Native
{
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
internal delegate int PersistZoneSet(
[MarshalAs(UnmanagedType.LPWStr)] string activeKey,
[MarshalAs(UnmanagedType.LPWStr)] string key,
ushort layoutId,
int zoneCount,
[MarshalAs(UnmanagedType.LPArray)] int[] zoneArray);
}
public void Persist(System.Windows.Int32Rect[] zones)
{
// Persist the editor data
Registry.SetValue(c_fullRegistryPath, Name, GetPersistData(), Microsoft.Win32.RegistryValueKind.Binary);
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];
var graphics = System.Drawing.Graphics.FromHwnd(IntPtr.Zero);
float dpi = graphics.DpiX / 96;
for (int i = 0; i < zones.Length; i++)
{
var left = (int)(zones[i].X * dpi);
var top = (int)(zones[i].Y * dpi);
var right = left + (int)(zones[i].Width * dpi);
var bottom = top + (int)(zones[i].Height * dpi);
var index = i * 4;
zoneArray[index] = left;
zoneArray[index+1] = top;
zoneArray[index+2] = right;
zoneArray[index+3] = bottom;
}
string[] args = Environment.GetCommandLineArgs();
if (args.Length > 1)
{
// args[1] = registry key value of currently active ZoneSet
// args[2] = id of layout to load at startup
string uniqueId = args[1];
// TODO: multimon
double height = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;
double width = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;
var key = width.ToString() + "_" + height.ToString();
var persistZoneSet = Marshal.GetDelegateForFunctionPointer<Native.PersistZoneSet>(pfn);
persistZoneSet(uniqueId, key, _id, zoneCount, zoneArray);
}
}
private static readonly string c_registryPath = Settings.RegistryPath + "\\Layouts";
private static readonly string c_fullRegistryPath = Settings.FullRegistryPath + "\\Layouts";
}
}

View File

@@ -0,0 +1,304 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Collections;
using System.Collections.ObjectModel;
using FancyZonesEditor.Models;
using System.Windows.Documents;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
namespace FancyZonesEditor
{
//
// Settings
// These are the configuration settings used by the rest of the editor
// 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
{
public Settings()
{
Rect workArea = System.Windows.SystemParameters.WorkArea;
// Initialize the five default layout models: Focus, Columns, Rows, Grid, and PriorityGrid
_defaultModels = new List<LayoutModel>(5);
_focusModel = new CanvasLayoutModel("Focus", c_focusModelId, (int)workArea.Width, (int)workArea.Height);
_defaultModels.Add(_focusModel);
_columnsModel = new GridLayoutModel("Columns", c_columnsModelId);
_columnsModel.Rows = 1;
_columnsModel.RowPercents = new int[1] { c_multiplier };
_defaultModels.Add(_columnsModel);
_rowsModel = new GridLayoutModel("Rows", c_rowsModelId);
_rowsModel.Columns = 1;
_rowsModel.ColumnPercents = new int[1] { c_multiplier };
_defaultModels.Add(_rowsModel);
_gridModel = new GridLayoutModel("Grid", c_gridModelId);
_defaultModels.Add(_gridModel);
_priorityGridModel = new GridLayoutModel("Priority Grid", c_priorityGridModelId);
_defaultModels.Add(_priorityGridModel);
_blankCustomModel = new CanvasLayoutModel("Create new custom", c_blankCustomModelId, (int)workArea.Width, (int)workArea.Height);
_zoneCount = (int)Registry.GetValue(FullRegistryPath, "ZoneCount", 3);
_spacing = (int)Registry.GetValue(FullRegistryPath, "Spacing", 16);
_showSpacing = (int)Registry.GetValue(FullRegistryPath, "ShowSpacing", 1) == 1;
UpdateLayoutModels();
}
// ZoneCount - number of zones selected in the picker window
public int ZoneCount
{
get { return _zoneCount; }
set
{
if (_zoneCount != value)
{
_zoneCount = value;
Registry.SetValue(FullRegistryPath, "ZoneCount", _zoneCount, RegistryValueKind.DWord);
UpdateLayoutModels();
FirePropertyChanged("ZoneCount");
}
}
}
private int _zoneCount;
// Spacing - how much space in between zones of the grid do you want
public int Spacing
{
get { return _spacing; }
set
{
if (_spacing != value)
{
_spacing = value;
Registry.SetValue(FullRegistryPath, "Spacing", _spacing, RegistryValueKind.DWord);
FirePropertyChanged("Spacing");
}
}
}
private int _spacing;
// ShowSpacing - is the Spacing value used or ignored?
public bool ShowSpacing
{
get { return _showSpacing; }
set
{
if (_showSpacing != value)
{
_showSpacing = value;
Registry.SetValue(FullRegistryPath, "ShowSpacing", _showSpacing, RegistryValueKind.DWord);
FirePropertyChanged("ShowSpacing");
}
}
}
private bool _showSpacing;
// IsShiftKeyPressed - is the shift key currently being held down
public bool IsShiftKeyPressed
{
get { return _isShiftKeyPressed; }
set
{
if (_isShiftKeyPressed != value)
{
_isShiftKeyPressed = value;
FirePropertyChanged("IsShiftKeyPressed");
}
}
}
private bool _isShiftKeyPressed;
// IsCtrlKeyPressed - is the ctrl key currently being held down
public bool IsCtrlKeyPressed
{
get { return _isCtrlKeyPressed; }
set
{
if (_isCtrlKeyPressed != value)
{
_isCtrlKeyPressed = value;
FirePropertyChanged("IsCtrlKeyPressed");
}
}
}
private bool _isCtrlKeyPressed;
// UpdateLayoutModels
// Update the five default layouts based on the new ZoneCount
private void UpdateLayoutModels()
{
int previousZoneCount = _focusModel.Zones.Count;
// Update the "Focus" Default Layout
_focusModel.Zones.Clear();
Int32Rect focusZoneRect = new Int32Rect((int)(_focusModel.ReferenceWidth * 0.1), (int)(_focusModel.ReferenceHeight * 0.1), (int)(_focusModel.ReferenceWidth * 0.6), (int)(_focusModel.ReferenceHeight * 0.6));
int focusRectXIncrement = (ZoneCount <= 1) ? 0 : (int)(_focusModel.ReferenceWidth * 0.2) / (ZoneCount - 1);
int focusRectYIncrement = (ZoneCount <= 1) ? 0 : (int)(_focusModel.ReferenceHeight * 0.2) / (ZoneCount - 1);
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 int[ZoneCount];
for (int i = 0; i < ZoneCount; i++)
{
_rowsModel.CellChildMap[i, 0] = i;
_columnsModel.CellChildMap[0, i] = i;
_rowsModel.RowPercents[i] = c_multiplier / ZoneCount; // _columnsModel is sharing the same array
}
// Update the "Grid" Default Layout
int rows = 1;
int cols = 1;
int mergeCount = 0;
while (ZoneCount / rows >= rows)
{
rows++;
}
rows--;
cols = ZoneCount / rows;
if (ZoneCount % rows == 0)
{
// even grid
}
else
{
cols++;
mergeCount = rows - (ZoneCount % rows);
}
_gridModel.Rows = rows;
_gridModel.Columns = cols;
_gridModel.RowPercents = new int[rows];
_gridModel.ColumnPercents = new int[cols];
_gridModel.CellChildMap = new int[rows, cols];
for (int row = 0; row < rows; row++)
{
_gridModel.RowPercents[row] = c_multiplier / rows;
}
for (int col = 0; col < cols; col++)
{
_gridModel.ColumnPercents[col] = c_multiplier / cols;
}
int index = 0;
for (int col = cols - 1; col >= 0; col--)
{
for (int row = rows - 1; row >= 0; row--)
{
_gridModel.CellChildMap[row, col] = index++;
if (index == ZoneCount)
{
index--;
}
}
}
// Update the "Priority Grid" Default Layout
if (ZoneCount <= s_priorityData.Length)
{
_priorityGridModel.Reload(s_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 { return _defaultModels; } }
public ObservableCollection<LayoutModel> CustomModels
{
get
{
if (_customModels == null)
{
_customModels = LayoutModel.LoadCustomModels();
_customModels.Insert(0, _blankCustomModel);
}
return _customModels;
}
}
private 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 >= c_lastPrefinedId);
}
// implementation of INotifyProeprtyChanged
public event PropertyChangedEventHandler PropertyChanged;
// FirePropertyChanged -- wrapper that calls INPC.PropertyChanged
protected virtual void FirePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
// storage for Default Layout Models
private IList<LayoutModel> _defaultModels;
private CanvasLayoutModel _focusModel;
private GridLayoutModel _rowsModel;
private GridLayoutModel _columnsModel;
private GridLayoutModel _gridModel;
private GridLayoutModel _priorityGridModel;
private CanvasLayoutModel _blankCustomModel;
private static readonly ushort c_focusModelId = 0xFFFF;
private static readonly ushort c_rowsModelId = 0xFFFE;
private static readonly ushort c_columnsModelId = 0xFFFD;
private static readonly ushort c_gridModelId = 0xFFFC;
private static readonly ushort c_priorityGridModelId = 0xFFFB;
private static readonly ushort c_blankCustomModelId = 0xFFFA;
private static readonly ushort c_lastPrefinedId = c_blankCustomModelId;
// hard coded data for all the "Priority Grid" configurations that are unique to "Grid"
private static byte[][] s_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 c_multiplier = 10000;
}
}