mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-24 04:12:32 +08:00
[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:
parent
eb15cdde1b
commit
646d61bd4d
1
.github/actions/spell-check/expect.txt
vendored
1
.github/actions/spell-check/expect.txt
vendored
@ -2374,6 +2374,7 @@ Whichdoes
|
||||
whitespaces
|
||||
WIC
|
||||
Wifi
|
||||
wifstream
|
||||
wih
|
||||
wiki
|
||||
wikipedia
|
||||
|
@ -374,8 +374,9 @@
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.FancyZonesProjectName)\FancyZonesEditor.runtimeconfig.json" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.FancyZonesProjectName)\FancyZonesEditor.exe" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.FancyZonesProjectName)\ControlzEx.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.FancyZonesProjectName)\MahApps.Metro.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.FancyZonesProjectName)\Microsoft.Xaml.Behaviors.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.FancyZonesProjectName)\ModernWpf.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.FancyZonesProjectName)\ModernWpf.Controls.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.FancyZonesProjectName)\System.Text.Json.dll" />
|
||||
<File Id="FancyZones_ManagedCommon" Source="$(var.BinX64Dir)modules\$(var.FancyZonesProjectName)\ManagedCommon.dll" />
|
||||
<File Id="FancyZones_Telemetry.dll" Source="$(var.BinX64Dir)modules\$(var.FancyZonesProjectName)\ManagedTelemetry.dll" />
|
||||
|
@ -2,20 +2,29 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
Startup="OnStartup">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
|
||||
<!-- Accent and AppTheme setting -->
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
|
||||
<ui:ThemeResources />
|
||||
<ui:XamlControlsResources />
|
||||
<ResourceDictionary Source="pack://application:,,,/Styles/ButtonStyles.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/Styles/LayoutPreviewStyles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<SolidColorBrush x:Key="CanvasZoneBackgroundBrush" Color="#BF333333"/>
|
||||
<SolidColorBrush x:Key="GridZoneBackgroundBrush" Color="#FF1a1a1a"/>
|
||||
|
||||
<Style x:Key="UWPFocusVisualStyle">
|
||||
<Setter Property="Control.Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Border Margin="-2"
|
||||
CornerRadius="4"
|
||||
BorderThickness="2"
|
||||
BorderBrush="{DynamicResource PrimaryForegroundBrush}" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
@ -9,6 +9,8 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using FancyZonesEditor.Utils;
|
||||
using ManagedCommon;
|
||||
@ -41,6 +43,9 @@ namespace FancyZonesEditor
|
||||
private const string CrashReportDynamicAssemblyTag = "dynamic assembly doesn't have location";
|
||||
private const string CrashReportLocationNullTag = "location is null or empty";
|
||||
|
||||
private const string ParsingErrorReportTag = "Settings parsing error";
|
||||
private const string ParsingErrorDataTag = "Data: ";
|
||||
|
||||
public MainWindowSettingsModel MainWindowSettings { get; }
|
||||
|
||||
public static FancyZonesEditorIO FancyZonesEditorIO { get; private set; }
|
||||
@ -49,6 +54,8 @@ namespace FancyZonesEditor
|
||||
|
||||
public static int PowerToysPID { get; set; }
|
||||
|
||||
private ThemeManager _themeManager;
|
||||
|
||||
public static bool DebugMode
|
||||
{
|
||||
get
|
||||
@ -67,7 +74,7 @@ namespace FancyZonesEditor
|
||||
|
||||
public App()
|
||||
{
|
||||
DebugModeCheck();
|
||||
// DebugModeCheck();
|
||||
FancyZonesEditorIO = new FancyZonesEditorIO();
|
||||
Overlay = new Overlay();
|
||||
MainWindowSettings = new MainWindowSettingsModel();
|
||||
@ -82,8 +89,61 @@ namespace FancyZonesEditor
|
||||
Environment.Exit(0);
|
||||
});
|
||||
|
||||
FancyZonesEditorIO.ParseCommandLineArguments();
|
||||
FancyZonesEditorIO.ParseDeviceInfoData();
|
||||
_themeManager = new ThemeManager(this);
|
||||
|
||||
if (!FancyZonesEditorIO.ParseParams().Result)
|
||||
{
|
||||
FancyZonesEditorIO.ParseCommandLineArguments();
|
||||
}
|
||||
|
||||
var parseResult = FancyZonesEditorIO.ParseZoneSettings();
|
||||
|
||||
// 10ms retry loop with 1 second timeout
|
||||
if (!parseResult.Result)
|
||||
{
|
||||
CancellationTokenSource ts = new CancellationTokenSource();
|
||||
Task t = Task.Run(() =>
|
||||
{
|
||||
while (!parseResult.Result && !ts.IsCancellationRequested)
|
||||
{
|
||||
Task.Delay(10).Wait();
|
||||
parseResult = FancyZonesEditorIO.ParseZoneSettings();
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
bool result = t.Wait(1000, ts.Token);
|
||||
ts.Cancel();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
ts.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Error message if parsing failed
|
||||
if (!parseResult.Result)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("## " + ParsingErrorReportTag);
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(parseResult.Message);
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(ParsingErrorDataTag);
|
||||
sb.AppendLine(parseResult.MalformedData);
|
||||
|
||||
string message = parseResult.Message + Environment.NewLine + Environment.NewLine + FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_User_Choice;
|
||||
if (MessageBox.Show(message, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Title, MessageBoxButton.YesNo) == MessageBoxResult.No)
|
||||
{
|
||||
// TODO: log error
|
||||
ShowExceptionReportMessageBox(sb.ToString());
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
ShowExceptionReportMessageBox(sb.ToString());
|
||||
}
|
||||
|
||||
MainWindowSettingsModel settings = ((App)Current).MainWindowSettings;
|
||||
settings.UpdateSelectedLayoutModel();
|
||||
|
@ -1,202 +1,69 @@
|
||||
<local:EditorWindow x:Class="FancyZonesEditor.CanvasEditorWindow"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Canvas_Layout_Editor}"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
xmlns:props="clr-namespace:FancyZonesEditor.Properties"
|
||||
mc:Ignorable="d"
|
||||
Title=""
|
||||
Width="528"
|
||||
SizeToContent="Height"
|
||||
Background="White"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Closed="OnClosed">
|
||||
AutomationProperties.Name="{x:Static props:Resources.Canvas_Layout_Editor}"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
xmlns:props="clr-namespace:FancyZonesEditor.Properties"
|
||||
mc:Ignorable="d"
|
||||
Title=""
|
||||
Width="320"
|
||||
BorderThickness="0"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
ui:WindowHelper.UseModernWindowStyle="True"
|
||||
ui:TitleBar.IsIconVisible="True"
|
||||
SizeToContent="Height"
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Closed="OnClosed">
|
||||
<Grid>
|
||||
<Grid Height="36"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
Margin="0,-36,0,0"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Border Background="{DynamicResource TitleBarSecondaryForegroundBrush}"
|
||||
Width="30"
|
||||
Height="3"
|
||||
CornerRadius="1.5"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,4,0,0" />
|
||||
</Grid>
|
||||
<StackPanel Margin="16"
|
||||
FocusManager.FocusedElement="{Binding ElementName=newZoneButton}">
|
||||
|
||||
<Button x:Name="newZoneButton"
|
||||
AutomationProperties.LabeledBy="{Binding ElementName=newZoneName}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Height="64"
|
||||
Width="64"
|
||||
ui:ControlHelper.CornerRadius="64"
|
||||
Margin="0,8,0,0"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Content=""
|
||||
FontSize="24"
|
||||
ToolTip="{x:Static props:Resources.Add_zone}"
|
||||
Click="OnAddZone" />
|
||||
|
||||
<Window.Resources>
|
||||
<Style x:Key="titleText" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
<Setter Property="LineHeight" Value="24" />
|
||||
<Setter Property="FontSize" Value="18"/>
|
||||
<Setter Property="Margin" Value="16,16,0,12" />
|
||||
</Style>
|
||||
<Style x:Key="zoneCount" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="Regular" />
|
||||
<Setter Property="FontSize" Value="24"/>
|
||||
<Setter Property="LineHeight" Value="24" />
|
||||
<Setter Property="Margin" Value="20,0,20,0" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
<Style x:Key="tabText" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="#C4C4C4"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="LineHeight" Value="20" />
|
||||
<Setter Property="Margin" Value="24,20,0,0" />
|
||||
<Setter Property="TextAlignment" Value="Center" />
|
||||
</Style>
|
||||
<Style x:Key="settingText" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="LineHeight" Value="20" />
|
||||
<Setter Property="Margin" Value="5,10,0,0" />
|
||||
<Setter Property="TextAlignment" Value="Left" />
|
||||
</Style>
|
||||
<Style x:Key="templateTitleText" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="Regular" />
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Margin" Value="0,20,0,0" />
|
||||
<Setter Property="TextAlignment" Value="Center" />
|
||||
<Setter Property="Height" Value="30"/>
|
||||
<Setter Property="Width" Value="250"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
<Style x:Key="customButtonFocusVisualStyle">
|
||||
<Setter Property="Control.Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Rectangle Margin="1" Stroke="White" StrokeDashArray="1 2" StrokeThickness="1" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="secondaryButton" TargetType="Button">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="0,5,0,5"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="#767676"/>
|
||||
<Setter Property="Margin" Value="16,10,0,0" />
|
||||
<Setter Property="Width" Value="239"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{DynamicResource customButtonFocusVisualStyle}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border Background="{TemplateBinding Background}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="#5D5D5D"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style x:Key="primaryButton" TargetType="Button">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="0,5,0,5"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="#0078D7"/>
|
||||
<Setter Property="Margin" Value="16,10,0,0" />
|
||||
<Setter Property="Width" Value="239"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{DynamicResource customButtonFocusVisualStyle}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border Background="{TemplateBinding Background}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="#024D89"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style x:Key="spinnerButton" TargetType="Button">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="FontSize" Value="24"/>
|
||||
<Setter Property="Padding" Value="0,0,0,5"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="#F2F2F2"/>
|
||||
<Setter Property="Margin" Value="0,0,0,0" />
|
||||
</Style>
|
||||
<Style x:Key="templateBackground" TargetType="Rectangle">
|
||||
<Setter Property="Fill" Value="Black"/>
|
||||
<Setter Property="Opacity" Value="0.05"/>
|
||||
<Setter Property="RadiusX" Value="4"/>
|
||||
<Setter Property="RadiusY" Value="4"/>
|
||||
</Style>
|
||||
<Style x:Key="templateBackgroundSelected" TargetType="Rectangle">
|
||||
<Setter Property="Fill" Value="#F2F2F2"/>
|
||||
<Setter Property="Opacity" Value="1"/>
|
||||
<Setter Property="RadiusX" Value="4"/>
|
||||
<Setter Property="RadiusY" Value="4"/>
|
||||
<Setter Property="Stroke" Value="#0078D7"/>
|
||||
<Setter Property="StrokeThickness" Value="2"/>
|
||||
</Style>
|
||||
<Style x:Key="newZoneButton" TargetType="Button">
|
||||
<Setter Property="Background" Value="#f2f2f2"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="FontFamily" Value="SegoeUI"/>
|
||||
<Setter Property="FontWeight" Value="Light"/>
|
||||
<Setter Property="FontSize" Value="120"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
<Style x:Key="textLabel" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="SegoeUI"/>
|
||||
<Setter Property="FontWeight" Value="Regular"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="16,12,0,0"/>
|
||||
</Style>
|
||||
<Style x:Key="textBox" TargetType="TextBox">
|
||||
<Setter Property="BorderBrush" Value="#949494"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="FontFamily" Value="SegoeUI"/>
|
||||
<Setter Property="FontWeight" Value="Regular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="Margin" Value="0,5,0,0"/>
|
||||
<Setter Property="Padding" Value="5,5,5,5"/>
|
||||
</Style>
|
||||
|
||||
</Window.Resources>
|
||||
<StackPanel FocusManager.FocusedElement="{Binding ElementName=newZoneButton}">
|
||||
<TextBlock Name="windowEditorDialogTitle" Text="{x:Static props:Resources.Custom_Layout_Creator}" Style="{StaticResource titleText}" />
|
||||
<Button x:Name="newZoneButton" AutomationProperties.LabeledBy="{Binding ElementName=newZoneName}" Width="496" Height="136" Style="{StaticResource newZoneButton}" Click="OnAddZone">
|
||||
<StackPanel>
|
||||
<TextBlock x:Name="newZoneName" Text="{x:Static props:Resources.Add_zone}" Style="{StaticResource templateTitleText}" />
|
||||
<TextBlock HorizontalAlignment="Center" Text="+" Margin="0,-40,0,0"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<TextBlock x:Name="customLayoutName" Text="{x:Static props:Resources.Name}" Style="{StaticResource textLabel}" />
|
||||
<TextBox Text="{Binding Name}" AutomationProperties.LabeledBy="{Binding ElementName=customLayoutName}" Width="496" Style="{StaticResource textBox}" />
|
||||
<!--
|
||||
<StackPanel Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<CheckBox x:Name="showGridSetting" VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="True" Margin="16,4,0,0"/>
|
||||
<TextBlock Text="Show snap grid" Style="{StaticResource settingText}" />
|
||||
<TextBlock Text="Grid spacing" Style="{StaticResource settingText}" Margin="40,10,10,0" />
|
||||
<TextBox x:Name="gridValue" Text="{Binding Path=Spacing,Mode=TwoWay}" Style="{StaticResource textBox}"/>
|
||||
<Grid Margin="0,24,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="8" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Content="{x:Static props:Resources.Cancel}"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Grid.Column="2"
|
||||
Click="OnCancel" />
|
||||
<Button Content="{x:Static props:Resources.Save_Apply}"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="OnSaveApplyTemplate" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
-->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,12,0,16">
|
||||
<Button Content="{x:Static props:Resources.Cancel}" Style="{StaticResource secondaryButton}" Click="OnCancel"/>
|
||||
<Button Content="{x:Static props:Resources.Save_Apply}" Style="{StaticResource primaryButton}" Click="OnSaveApplyTemplate" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:EditorWindow>
|
||||
</Grid>
|
||||
</local:EditorWindow>
|
@ -8,11 +8,23 @@ using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for windowEditor.xaml
|
||||
/// </summary>
|
||||
public partial class CanvasEditorWindow : EditorWindow
|
||||
{
|
||||
// Default distance from the top and left borders to the zone.
|
||||
private const int DefaultOffset = 100;
|
||||
|
||||
// Next created zone will be by OffsetShift value below and to the right of the previous.
|
||||
private const int OffsetShift = 50;
|
||||
|
||||
// Zone size depends on the work area size multiplied by ZoneSizeMultiplier value.
|
||||
private const double ZoneSizeMultiplier = 0.4;
|
||||
|
||||
// Distance from the top and left borders to the zone.
|
||||
private int _offset = DefaultOffset;
|
||||
|
||||
private CanvasLayoutModel _model;
|
||||
private CanvasLayoutModel _stashedModel;
|
||||
|
||||
public CanvasEditorWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
@ -28,19 +40,19 @@ namespace FancyZonesEditor
|
||||
Rect workingArea = App.Overlay.WorkArea;
|
||||
int offset = (int)App.Overlay.ScaleCoordinateWithCurrentMonitorDpi(_offset);
|
||||
|
||||
if (offset + (int)(workingArea.Width * 0.4) < (int)workingArea.Width
|
||||
&& offset + (int)(workingArea.Height * 0.4) < (int)workingArea.Height)
|
||||
if (offset + (int)(workingArea.Width * ZoneSizeMultiplier) < (int)workingArea.Width
|
||||
&& offset + (int)(workingArea.Height * ZoneSizeMultiplier) < (int)workingArea.Height)
|
||||
{
|
||||
_model.AddZone(new Int32Rect(offset, offset, (int)(workingArea.Width * 0.4), (int)(workingArea.Height * 0.4)));
|
||||
_model.AddZone(new Int32Rect(offset, offset, (int)(workingArea.Width * ZoneSizeMultiplier), (int)(workingArea.Height * ZoneSizeMultiplier)));
|
||||
}
|
||||
else
|
||||
{
|
||||
_offset = 100;
|
||||
_offset = DefaultOffset;
|
||||
offset = (int)App.Overlay.ScaleCoordinateWithCurrentMonitorDpi(_offset);
|
||||
_model.AddZone(new Int32Rect(offset, offset, (int)(workingArea.Width * 0.4), (int)(workingArea.Height * 0.4)));
|
||||
_model.AddZone(new Int32Rect(offset, offset, (int)(workingArea.Width * ZoneSizeMultiplier), (int)(workingArea.Height * ZoneSizeMultiplier)));
|
||||
}
|
||||
|
||||
_offset += 50; // TODO: replace hardcoded numbers
|
||||
_offset += OffsetShift;
|
||||
}
|
||||
|
||||
protected new void OnCancel(object sender, RoutedEventArgs e)
|
||||
@ -56,9 +68,5 @@ namespace FancyZonesEditor
|
||||
OnCancel(sender, null);
|
||||
}
|
||||
}
|
||||
|
||||
private int _offset = 100;
|
||||
private CanvasLayoutModel _model;
|
||||
private CanvasLayoutModel _stashedModel;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,8 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:props="clr-namespace:FancyZonesEditor.Properties"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
mc:Ignorable="d"
|
||||
Background="Transparent"
|
||||
@ -15,7 +16,7 @@
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Thumb}">
|
||||
<Border x:Name="ThumbBorder" Opacity="0" BorderBrush="{Binding Source={x:Static SystemParameters.WindowGlassBrush}}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
|
||||
<Border x:Name="ThumbBorder" Opacity="0" BorderBrush="{DynamicResource SystemControlBackgroundAccentBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates" >
|
||||
<VisualStateGroup.Transitions>
|
||||
@ -43,16 +44,27 @@
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryForegroundBrush}" />
|
||||
<Setter Property="Padding" Value="1"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
|
||||
<ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||
<Border x:Name="border"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}"
|
||||
SnapsToDevicePixels="true">
|
||||
<ContentPresenter x:Name="contentPresenter"
|
||||
Focusable="False"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsDefaulted" Value="true">
|
||||
<Setter Property="BorderBrush" TargetName="border" Value="{Binding Source={x:Static SystemParameters.WindowGlassBrush}}"/>
|
||||
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource SystemControlBackgroundAccentBrush}"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter Property="Opacity" TargetName="contentPresenter" Value="0.6"/>
|
||||
@ -67,7 +79,10 @@
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border BorderBrush="{Binding Source={x:Static SystemParameters.WindowGlassBrush}}" Background="{StaticResource CanvasZoneBackgroundBrush}" BorderThickness="1">
|
||||
<Border BorderBrush="{DynamicResource SystemControlBackgroundAccentBrush}"
|
||||
Background="{DynamicResource CanvasZoneBackgroundBrush}"
|
||||
CornerRadius="4"
|
||||
BorderThickness="1">
|
||||
<Grid x:Name="Frame">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="8"/>
|
||||
@ -89,8 +104,8 @@
|
||||
Canvas.Left="10"
|
||||
Canvas.Bottom="10"
|
||||
FontSize="64"
|
||||
FontFamily="Segoe UI Light"
|
||||
Foreground="White"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Grid.Column="2"
|
||||
Grid.Row="2"
|
||||
VerticalContentAlignment="Center"
|
||||
@ -108,10 +123,20 @@
|
||||
<Thumb x:Name="SWResize" Cursor="SizeNESW" BorderThickness="3,0,0,3" Grid.Row="3" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" DragDelta="UniversalDragDelta" DragStarted="SWResize_DragStarted" Style="{DynamicResource CanvasZoneThumbStyle}"/>
|
||||
<Thumb x:Name="SEResize" Cursor="SizeNWSE" BorderThickness="0,0,3,3" Grid.Row="3" Grid.Column="3" Grid.RowSpan="2" Grid.ColumnSpan="2" DragDelta="UniversalDragDelta" DragStarted="SEResize_DragStarted" Style="{DynamicResource CanvasZoneThumbStyle}"/>
|
||||
|
||||
<Button Content="" BorderThickness="0" ToolTip="Delete zone" Background="Transparent" Foreground="White" FontSize="16" Padding="4" Click="OnClose" Grid.Row="2" Grid.Column="2" FontFamily="Segoe MDL2 Assets" HorizontalAlignment="Right" VerticalAlignment="Top" Style="{DynamicResource CloseButtonStyle}"/>
|
||||
<Button Content=""
|
||||
BorderThickness="0"
|
||||
ToolTip="{x:Static props:Resources.Delete_Zone}"
|
||||
Background="Transparent"
|
||||
FontSize="16"
|
||||
Padding="4"
|
||||
Click="OnClose"
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top" Style="{DynamicResource CloseButtonStyle}"/>
|
||||
|
||||
<Canvas x:Name="Body" />
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
|
@ -0,0 +1,25 @@
|
||||
// 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.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor.Converters
|
||||
{
|
||||
public class LayoutModelTypeBlankToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return (LayoutType)value == LayoutType.Blank ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,24 +3,22 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor.Converters
|
||||
{
|
||||
public class BooleanToBrushConverter : IValueConverter
|
||||
public class LayoutModelTypeToVisibilityConverter : IValueConverter
|
||||
{
|
||||
private static readonly Brush _selectedBrush = new SolidColorBrush(Color.FromRgb(0x00, 0x78, 0xD7));
|
||||
private static readonly Brush _normalBrush = new SolidColorBrush(Color.FromRgb(0xF2, 0xF2, 0xF2));
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return ((bool)value) ? _selectedBrush : _normalBrush;
|
||||
return value is CanvasLayoutModel ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return value == _selectedBrush;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
// 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.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor.Converters
|
||||
{
|
||||
public class LayoutTypeCustomToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return (LayoutType)value == LayoutType.Custom ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
// 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.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor.Converters
|
||||
{
|
||||
public class LayoutTypeTemplateToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return (LayoutType)value != LayoutType.Custom ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -5,11 +5,10 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using FancyZonesEditor.Models;
|
||||
using MahApps.Metro.Controls;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
public class EditorWindow : MetroWindow
|
||||
public class EditorWindow : Window
|
||||
{
|
||||
protected void OnSaveApplyTemplate(object sender, RoutedEventArgs e)
|
||||
{
|
||||
@ -24,9 +23,13 @@ namespace FancyZonesEditor
|
||||
}
|
||||
|
||||
model.Persist();
|
||||
|
||||
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
||||
settings.SetAppliedModel(model);
|
||||
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
||||
}
|
||||
|
||||
LayoutModel.SerializeDeletedCustomZoneSets();
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
|
||||
_backToLayoutPicker = false;
|
||||
Close();
|
||||
|
@ -65,19 +65,14 @@
|
||||
</AdditionalFiles>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MahApps.Metro" Version="2.3.2" />
|
||||
<PackageReference Include="System.IO.Abstractions" Version="12.2.5" />
|
||||
<PackageReference Include="System.Text.Json" Version="4.7.2" />
|
||||
<PackageReference Include="ControlzEx" Version="4.4.0" />
|
||||
<PackageReference Include="ModernWpfUI" Version="0.9.3" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="images\ChromeClose.png" />
|
||||
<Resource Include="images\Delete.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="images\Merge.png" />
|
||||
<PackageReference Include="System.IO.Abstractions" Version="12.2.5" />
|
||||
<PackageReference Include="System.Text.Json" Version="4.7.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="images\FancyZonesEditor.ico" />
|
||||
@ -86,6 +81,11 @@
|
||||
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
|
@ -7,7 +7,6 @@ using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using FancyZonesEditor.Models;
|
||||
using FancyZonesEditor.Utils;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
@ -120,25 +119,29 @@ namespace FancyZonesEditor
|
||||
{
|
||||
_colInfo.Add(new RowColInfo(model.ColumnPercents[col]));
|
||||
}
|
||||
|
||||
int maxIndex = 0;
|
||||
for (int row = 0; row < _model.Rows; row++)
|
||||
{
|
||||
for (int col = 0; col < _model.Columns; col++)
|
||||
{
|
||||
maxIndex = Math.Max(maxIndex, _model.CellChildMap[row, col]);
|
||||
}
|
||||
}
|
||||
|
||||
_zoneCount = maxIndex + 1;
|
||||
}
|
||||
|
||||
public int ZoneCount
|
||||
{
|
||||
get
|
||||
{
|
||||
int maxIndex = 0;
|
||||
for (int row = 0; row < _model.Rows; row++)
|
||||
{
|
||||
for (int col = 0; col < _model.Columns; col++)
|
||||
{
|
||||
maxIndex = Math.Max(maxIndex, _model.CellChildMap[row, col]);
|
||||
}
|
||||
}
|
||||
|
||||
return maxIndex;
|
||||
return _zoneCount;
|
||||
}
|
||||
}
|
||||
|
||||
private int _zoneCount;
|
||||
|
||||
public Tuple<int, int> RowColByIndex(int index)
|
||||
{
|
||||
int foundRow = -1;
|
||||
@ -238,6 +241,7 @@ namespace FancyZonesEditor
|
||||
FixAccuracyError(_colInfo, _model.ColumnPercents);
|
||||
_model.CellChildMap = newCellChildMap;
|
||||
_model.Columns++;
|
||||
_model.UpdatePreview();
|
||||
}
|
||||
|
||||
public void SplitRow(int foundRow, int spliteeIndex, int newChildIndex, double space, double offset, double actualHeight)
|
||||
@ -289,6 +293,7 @@ namespace FancyZonesEditor
|
||||
FixAccuracyError(_rowInfo, _model.RowPercents);
|
||||
_model.CellChildMap = newCellChildMap;
|
||||
_model.Rows++;
|
||||
_model.UpdatePreview();
|
||||
}
|
||||
|
||||
public void SplitOnDrag(GridResizer resizer, double delta, double space)
|
||||
@ -447,6 +452,8 @@ namespace FancyZonesEditor
|
||||
_model.CellChildMap = newCellChildMap;
|
||||
_model.Rows++;
|
||||
}
|
||||
|
||||
_model.UpdatePreview();
|
||||
}
|
||||
|
||||
public void RecalculateZones(int spacing, Size arrangeSize)
|
||||
@ -474,6 +481,11 @@ namespace FancyZonesEditor
|
||||
|
||||
public void ArrangeZones(UIElementCollection zones, int spacing)
|
||||
{
|
||||
if (zones.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int rows = _model.Rows;
|
||||
int cols = _model.Columns;
|
||||
int[,] cells = _model.CellChildMap;
|
||||
@ -1029,6 +1041,7 @@ namespace FancyZonesEditor
|
||||
|
||||
_model.Rows = rows;
|
||||
_model.Columns = cols;
|
||||
_model.UpdatePreview();
|
||||
}
|
||||
|
||||
private void FixAccuracyError(List<RowColInfo> info, List<int> percents)
|
||||
|
@ -5,47 +5,40 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:props="clr-namespace:FancyZonesEditor.Properties"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="Black" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Background" Value="#F2F2F2" />
|
||||
<Setter Property="Width" Value="150" />
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<Viewbox Stretch="Uniform">
|
||||
<Grid>
|
||||
<Canvas x:Name="Preview" />
|
||||
<Canvas x:Name="AdornerLayer" />
|
||||
<Canvas
|
||||
x:Name="MergePanel"
|
||||
MouseUp="MergePanelMouseUp"
|
||||
Visibility="Collapsed">
|
||||
|
||||
<StackPanel
|
||||
x:Name="MergeButtons"
|
||||
Background="Gray"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Width="134"
|
||||
Height="36"
|
||||
Margin="0"
|
||||
Click="MergeClick">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image
|
||||
Height="16"
|
||||
Margin="0,0,12,0"
|
||||
HorizontalAlignment="Left"
|
||||
Source="images/Merge.png" />
|
||||
<TextBlock Text="Merge zones" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Canvas x:Name="MergePanel"
|
||||
MouseUp="MergePanelMouseUp"
|
||||
Visibility="Collapsed">
|
||||
<Canvas.Effect>
|
||||
<DropShadowEffect BlurRadius="6" Opacity="0.32" ShadowDepth="2" />
|
||||
</Canvas.Effect>
|
||||
<StackPanel x:Name="MergeButtons"
|
||||
Orientation="Horizontal">
|
||||
<Border CornerRadius="2"
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}">
|
||||
|
||||
<Button Width="134"
|
||||
Height="36"
|
||||
Margin="0"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
Click="MergeClick">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Margin="0,3,8,0" />
|
||||
<TextBlock Text="{x:Static props:Resources.Merge_zones}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Canvas>
|
||||
</Grid>
|
||||
|
@ -8,7 +8,6 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using FancyZonesEditor.Models;
|
||||
using FancyZonesEditor.Utils;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
@ -40,27 +39,27 @@ namespace FancyZonesEditor
|
||||
private void GridEditor_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
GridLayoutModel model = (GridLayoutModel)DataContext;
|
||||
if (model != null)
|
||||
if (model == null)
|
||||
{
|
||||
_data = new GridData(model);
|
||||
_dragHandles = new GridDragHandles(AdornerLayer.Children, Resizer_DragDelta, Resizer_DragCompleted);
|
||||
|
||||
int zoneCount = _data.ZoneCount;
|
||||
for (int i = 0; i <= zoneCount; i++)
|
||||
{
|
||||
AddZone();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_data = new GridData(model);
|
||||
_dragHandles = new GridDragHandles(AdornerLayer.Children, Resizer_DragDelta, Resizer_DragCompleted);
|
||||
_dragHandles.InitDragHandles(model);
|
||||
|
||||
Model = model;
|
||||
if (Model == null)
|
||||
Model.PropertyChanged += OnGridDimensionsChanged;
|
||||
|
||||
int zoneCount = _data.ZoneCount;
|
||||
for (int i = 0; i < zoneCount; i++)
|
||||
{
|
||||
Model = new GridLayoutModel();
|
||||
DataContext = Model;
|
||||
AddZone();
|
||||
}
|
||||
|
||||
Model.PropertyChanged += OnGridDimensionsChanged;
|
||||
_dragHandles.InitDragHandles(model);
|
||||
Rect workingArea = App.Overlay.WorkArea;
|
||||
Size actualSize = new Size(workingArea.Width, workingArea.Height);
|
||||
ArrangeGridRects(actualSize);
|
||||
}
|
||||
|
||||
private void GridEditor_Unloaded(object sender, RoutedEventArgs e)
|
||||
@ -330,15 +329,17 @@ namespace FancyZonesEditor
|
||||
zone.Visibility = Visibility.Visible;
|
||||
return freeIndex;
|
||||
}
|
||||
|
||||
zone = new GridZone(Model.ShowSpacing ? Model.Spacing : 0);
|
||||
zone.Split += OnSplit;
|
||||
zone.MergeDrag += OnMergeDrag;
|
||||
zone.MergeComplete += OnMergeComplete;
|
||||
zone.FullSplit += OnFullSplit;
|
||||
Preview.Children.Add(zone);
|
||||
return Preview.Children.Count - 1;
|
||||
}
|
||||
|
||||
zone = new GridZone();
|
||||
zone.Split += OnSplit;
|
||||
zone.MergeDrag += OnMergeDrag;
|
||||
zone.MergeComplete += OnMergeComplete;
|
||||
zone.FullSplit += OnFullSplit;
|
||||
Preview.Children.Add(zone);
|
||||
return Preview.Children.Count - 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void OnGridDimensionsChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
@ -372,7 +373,7 @@ namespace FancyZonesEditor
|
||||
Preview.Height = workArea.Height;
|
||||
|
||||
GridLayoutModel model = Model;
|
||||
if (model == null)
|
||||
if (model == null || _data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -383,9 +384,7 @@ namespace FancyZonesEditor
|
||||
return;
|
||||
}
|
||||
|
||||
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
||||
|
||||
int spacing = settings.ShowSpacing ? settings.Spacing : 0;
|
||||
int spacing = model.ShowSpacing ? model.Spacing : 0;
|
||||
|
||||
_data.RecalculateZones(spacing, arrangeSize);
|
||||
_data.ArrangeZones(Preview.Children, spacing);
|
||||
@ -411,10 +410,10 @@ namespace FancyZonesEditor
|
||||
if (_dragHandles.HasSnappedNonAdjacentResizers(resizer))
|
||||
{
|
||||
double spacing = 0;
|
||||
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
||||
if (settings.ShowSpacing)
|
||||
GridLayoutModel model = Model;
|
||||
if (model.ShowSpacing)
|
||||
{
|
||||
spacing = settings.Spacing;
|
||||
spacing = model.Spacing;
|
||||
}
|
||||
|
||||
_data.SplitOnDrag(resizer, delta, spacing);
|
||||
|
@ -1,196 +1,62 @@
|
||||
<local:EditorWindow x:Class="FancyZonesEditor.GridEditorWindow"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Grid_Layout_Editor}"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
xmlns:props="clr-namespace:FancyZonesEditor.Properties"
|
||||
mc:Ignorable="d"
|
||||
Title=""
|
||||
Width="528"
|
||||
SizeToContent="Height"
|
||||
Background="White"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Closed="OnClosed">
|
||||
AutomationProperties.Name="{x:Static props:Resources.Grid_Layout_Editor}"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
xmlns:props="clr-namespace:FancyZonesEditor.Properties"
|
||||
mc:Ignorable="d"
|
||||
Title=""
|
||||
Width="320"
|
||||
BorderThickness="0"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
ui:WindowHelper.UseModernWindowStyle="True"
|
||||
ui:TitleBar.IsIconVisible="True"
|
||||
SizeToContent="Height"
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Closed="OnClosed">
|
||||
<Grid>
|
||||
<Grid
|
||||
Height="36"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
Margin="0,-36,0,0"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Stretch">
|
||||
|
||||
<Window.Resources>
|
||||
<Style x:Key="titleText" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
<Setter Property="LineHeight" Value="24" />
|
||||
<Setter Property="FontSize" Value="18"/>
|
||||
<Setter Property="Margin" Value="0,0,0,12" />
|
||||
</Style>
|
||||
<Style x:Key="zoneCount" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="Regular" />
|
||||
<Setter Property="FontSize" Value="24"/>
|
||||
<Setter Property="LineHeight" Value="24" />
|
||||
<Setter Property="Margin" Value="20,0,20,0" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
<Style x:Key="tabText" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="#C4C4C4"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="LineHeight" Value="20" />
|
||||
<Setter Property="Margin" Value="24,20,0,0" />
|
||||
<Setter Property="TextAlignment" Value="Center" />
|
||||
</Style>
|
||||
<Style x:Key="settingText" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="LineHeight" Value="20" />
|
||||
<Setter Property="Margin" Value="5,10,0,0" />
|
||||
<Setter Property="TextAlignment" Value="Left" />
|
||||
</Style>
|
||||
<Style x:Key="templateTitleText" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="Regular" />
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Margin" Value="0,20,0,0" />
|
||||
<Setter Property="TextAlignment" Value="Center" />
|
||||
<Setter Property="Height" Value="30"/>
|
||||
<Setter Property="Width" Value="250"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
<Style x:Key="customButtonFocusVisualStyle">
|
||||
<Setter Property="Control.Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Rectangle Margin="1" Stroke="White" StrokeDashArray="1 2" StrokeThickness="1" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="secondaryButton" TargetType="Button">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="0,5,0,5"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="#767676"/>
|
||||
<Setter Property="Width" Value="239"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{DynamicResource customButtonFocusVisualStyle}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border Background="{TemplateBinding Background}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="#5D5D5D"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style x:Key="primaryButton" TargetType="Button">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="0,5,0,5"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="#0078D7"/>
|
||||
<Setter Property="Margin" Value="16,0,0,0" />
|
||||
<Setter Property="Width" Value="239"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{DynamicResource customButtonFocusVisualStyle}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border Background="{TemplateBinding Background}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="#024D89"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style x:Key="spinnerButton" TargetType="Button">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="FontSize" Value="24"/>
|
||||
<Setter Property="Padding" Value="0,0,0,5"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="#F2F2F2"/>
|
||||
<Setter Property="Margin" Value="0,0,0,0" />
|
||||
</Style>
|
||||
<Style x:Key="templateBackground" TargetType="Rectangle">
|
||||
<Setter Property="Fill" Value="Black"/>
|
||||
<Setter Property="Opacity" Value="0.05"/>
|
||||
<Setter Property="RadiusX" Value="4"/>
|
||||
<Setter Property="RadiusY" Value="4"/>
|
||||
</Style>
|
||||
<Style x:Key="templateBackgroundSelected" TargetType="Rectangle">
|
||||
<Setter Property="Fill" Value="#F2F2F2"/>
|
||||
<Setter Property="Opacity" Value="1"/>
|
||||
<Setter Property="RadiusX" Value="4"/>
|
||||
<Setter Property="RadiusY" Value="4"/>
|
||||
<Setter Property="Stroke" Value="#0078D7"/>
|
||||
<Setter Property="StrokeThickness" Value="2"/>
|
||||
</Style>
|
||||
<Style x:Key="newZoneButton" TargetType="Button">
|
||||
<Setter Property="Background" Value="#f2f2f2"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="FontFamily" Value="SegoeUI"/>
|
||||
<Setter Property="FontWeight" Value="Light"/>
|
||||
<Setter Property="FontSize" Value="120"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
<Style x:Key="textLabel" TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="SegoeUI"/>
|
||||
<Setter Property="FontWeight" Value="Regular"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="0,12,0,0"/>
|
||||
</Style>
|
||||
<Style x:Key="textBox" TargetType="TextBox">
|
||||
<Setter Property="BorderBrush" Value="#949494"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="FontFamily" Value="SegoeUI"/>
|
||||
<Setter Property="FontWeight" Value="Regular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
|
||||
<Setter Property="Padding" Value="5,5,5,5"/>
|
||||
</Style>
|
||||
|
||||
</Window.Resources>
|
||||
<StackPanel Margin="16">
|
||||
<TextBlock Name="windowEditorDialogTitle" Text="{x:Static props:Resources.Custom_Table_Layout}" Style="{StaticResource titleText}" />
|
||||
|
||||
<TextBlock Text="{x:Static props:Resources.Note_Custom_Table}" Style="{StaticResource textLabel}" TextWrapping="Wrap" />
|
||||
<TextBlock x:Name="customLayoutName" Text="{x:Static props:Resources.Name}" Style="{StaticResource textLabel}" />
|
||||
<TextBox Name="customLayoutNameTextBox" Text="{Binding Name}" GotFocus="NameTextBox_GotFocus" AutomationProperties.LabeledBy="{Binding ElementName=customLayoutName}" Style="{StaticResource textBox}" />
|
||||
<!--
|
||||
<StackPanel Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<CheckBox x:Name="showGridSetting" VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="True" Margin="21,4,0,0"/>
|
||||
<TextBlock Text="Show snap grid" Style="{StaticResource settingText}" />
|
||||
<TextBlock Text="Grid spacing" Style="{StaticResource settingText}" Margin="40,10,10,0" />
|
||||
<TextBox x:Name="gridValue" Text="{Binding Path=Spacing,Mode=TwoWay}" Style="{StaticResource textBox}"/>
|
||||
<Border
|
||||
Background="{DynamicResource TitleBarSecondaryForegroundBrush}"
|
||||
Width="30"
|
||||
Height="3"
|
||||
CornerRadius="1.5"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,4,0,0" />
|
||||
</Grid>
|
||||
<StackPanel Margin="16">
|
||||
<TextBlock Text="{x:Static props:Resources.Note_Custom_Table}"
|
||||
Foreground="{DynamicResource SecondaryForegroundBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Margin="0,8,0,0"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<Grid Margin="0,24,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="8"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Content="{x:Static props:Resources.Cancel}"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Grid.Column="2"
|
||||
Click="OnCancel" />
|
||||
<Button Content="{x:Static props:Resources.Save_Apply}"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="OnSaveApplyTemplate" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
-->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,16,0,0">
|
||||
<Button Content="{x:Static props:Resources.Cancel}" Style="{StaticResource secondaryButton}" Click="OnCancel" />
|
||||
<Button Content="{x:Static props:Resources.Save_Apply}" Style="{StaticResource primaryButton}" Click="OnSaveApplyTemplate" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</local:EditorWindow>
|
@ -5,13 +5,9 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using FancyZonesEditor.Models;
|
||||
using FancyZonesEditor.Utils;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for Window2.xaml
|
||||
/// </summary>
|
||||
public partial class GridEditorWindow : EditorWindow
|
||||
{
|
||||
public GridEditorWindow()
|
||||
@ -42,15 +38,5 @@ namespace FancyZonesEditor
|
||||
}
|
||||
|
||||
private GridLayoutModel _stashedModel;
|
||||
|
||||
private void NameTextBox_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
customLayoutNameTextBox.CaretIndex = customLayoutNameTextBox.Text.Length;
|
||||
}
|
||||
|
||||
public System.Windows.Controls.TextBox NameTextBox()
|
||||
{
|
||||
return customLayoutNameTextBox;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,15 +8,32 @@
|
||||
d:DesignHeight="300" d:DesignWidth="300">
|
||||
<Thumb.Template>
|
||||
<ControlTemplate>
|
||||
<StackPanel x:Name="Body" Grid.Column="0" Width="48" Height="48">
|
||||
|
||||
<Ellipse x:Name="BackgroundEllipse" Height="48" Width="48" Fill="{Binding Source={x:Static SystemParameters.WindowGlassBrush}}" />
|
||||
<Rectangle Height="20" Width="2" Fill="White" Margin="5,-48,0,0"/>
|
||||
<Rectangle Height="20" Width="2" Fill="White" Margin="-5,-48,0,0"/>
|
||||
</StackPanel>
|
||||
<Border x:Name="Body"
|
||||
Height="48"
|
||||
Width="48"
|
||||
CornerRadius="48"
|
||||
Background="{DynamicResource SystemControlBackgroundAccentBrush}">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="6"
|
||||
Opacity="0.24"
|
||||
ShadowDepth="1" />
|
||||
</Border.Effect>
|
||||
<Grid>
|
||||
<Rectangle Height="20"
|
||||
Width="2"
|
||||
Fill="White"
|
||||
Margin="5,0,0,0" />
|
||||
<Rectangle Height="20"
|
||||
Width="2"
|
||||
Fill="White"
|
||||
Margin="-5,0,0,0" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter Property="Opacity" TargetName="BackgroundEllipse" Value="0.6"/>
|
||||
<Setter Property="Background"
|
||||
TargetName="Body"
|
||||
Value="{DynamicResource SystemAccentColorLight1Brush}"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
|
@ -45,7 +45,7 @@ namespace FancyZonesEditor
|
||||
{
|
||||
_orientation = value;
|
||||
ApplyTemplate();
|
||||
StackPanel body = (StackPanel)Template.FindName("Body", this);
|
||||
Border body = (Border)Template.FindName("Body", this);
|
||||
if (value == Orientation.Vertical)
|
||||
{
|
||||
body.RenderTransform = null;
|
||||
|
@ -4,13 +4,14 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
xmlns:props="clr-namespace:FancyZonesEditor.Properties"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
Background="{StaticResource GridZoneBackgroundBrush}"
|
||||
BorderBrush="{Binding Source={x:Static SystemParameters.WindowGlassBrush}}"
|
||||
Background="{DynamicResource GridZoneBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource SystemControlBackgroundAccentBrush}"
|
||||
BorderThickness="1"
|
||||
Opacity="0.8"
|
||||
Opacity="1"
|
||||
mc:Ignorable="d">
|
||||
<Grid x:Name="Frame">
|
||||
<Canvas x:Name="Body" />
|
||||
@ -23,9 +24,9 @@
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="ID"
|
||||
FontFamily="Segoe UI Light"
|
||||
FontWeight="SemiBold"
|
||||
FontSize="64"
|
||||
Foreground="White" />
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}" />
|
||||
<!--<TextBlock Margin="2" Text="Shift Key switches direction Ctrl Key repeats"/>-->
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
@ -59,7 +59,7 @@ namespace FancyZonesEditor
|
||||
set { SetValue(IsSelectedProperty, value); }
|
||||
}
|
||||
|
||||
public GridZone()
|
||||
public GridZone(int spacing)
|
||||
{
|
||||
InitializeComponent();
|
||||
OnSelectionChanged();
|
||||
@ -69,6 +69,9 @@ namespace FancyZonesEditor
|
||||
};
|
||||
Body.Children.Add(_splitter);
|
||||
|
||||
Spacing = spacing;
|
||||
SplitterThickness = Math.Max(spacing, 1);
|
||||
|
||||
((App)Application.Current).MainWindowSettings.PropertyChanged += ZoneSettings_PropertyChanged;
|
||||
}
|
||||
|
||||
@ -104,19 +107,9 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
|
||||
private int SplitterThickness
|
||||
{
|
||||
get
|
||||
{
|
||||
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
||||
if (!settings.ShowSpacing)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
private int Spacing { get; set; }
|
||||
|
||||
return Math.Max(settings.Spacing, 1);
|
||||
}
|
||||
}
|
||||
private int SplitterThickness { get; set; }
|
||||
|
||||
private void UpdateSplitter()
|
||||
{
|
||||
@ -282,14 +275,7 @@ namespace FancyZonesEditor
|
||||
|
||||
private void DoSplit(Orientation orientation, double offset)
|
||||
{
|
||||
int spacing = 0;
|
||||
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
||||
if (settings.ShowSpacing)
|
||||
{
|
||||
spacing = settings.Spacing;
|
||||
}
|
||||
|
||||
Split?.Invoke(this, new SplitEventArgs(orientation, offset, spacing));
|
||||
Split?.Invoke(this, new SplitEventArgs(orientation, offset, Spacing));
|
||||
}
|
||||
|
||||
private void FullSplit_Click(object sender, RoutedEventArgs e)
|
||||
|
@ -5,9 +5,11 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
mc:Ignorable="d"
|
||||
Title="FancyZones Layout" Height="450" Width="800"
|
||||
Title="FancyZones Layout"
|
||||
Height="450"
|
||||
Width="800"
|
||||
ShowInTaskbar="False"
|
||||
ResizeMode="NoResize"
|
||||
WindowStyle="None"
|
||||
AllowsTransparency="True"
|
||||
Background="Transparent"/>
|
||||
Background="{DynamicResource BackdropBrush}"/>
|
@ -6,8 +6,12 @@
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
mc:Ignorable="d"
|
||||
Loaded="OnLoaded"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid x:Name="Body">
|
||||
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Border CornerRadius="4"
|
||||
Background="{DynamicResource LayoutPreviewBackgroundBrush}" />
|
||||
<Grid x:Name="Body"
|
||||
Background="Transparent" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
@ -8,7 +8,6 @@ using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
@ -22,10 +21,11 @@ namespace FancyZonesEditor
|
||||
private const string PropertyZoneCountID = "ZoneCount";
|
||||
private const string PropertyShowSpacingID = "ShowSpacing";
|
||||
private const string PropertySpacingID = "Spacing";
|
||||
private const string PropertyZoneBackgroundID = "ZoneBackground";
|
||||
private const string PropertyZoneBorderID = "ZoneBorder";
|
||||
private const string ObjectDependencyID = "IsActualSize";
|
||||
|
||||
public static readonly DependencyProperty IsActualSizeProperty = DependencyProperty.Register(ObjectDependencyID, typeof(bool), typeof(LayoutPreview), new PropertyMetadata(false));
|
||||
|
||||
private LayoutModel _model;
|
||||
private List<Int32Rect> _zones = new List<Int32Rect>();
|
||||
|
||||
@ -49,8 +49,17 @@ namespace FancyZonesEditor
|
||||
|
||||
private void LayoutPreview_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (_model != null)
|
||||
{
|
||||
_model.PropertyChanged -= LayoutModel_PropertyChanged;
|
||||
}
|
||||
|
||||
_model = (LayoutModel)DataContext;
|
||||
RenderPreview();
|
||||
if (_model != null)
|
||||
{
|
||||
_model.PropertyChanged += LayoutModel_PropertyChanged;
|
||||
RenderPreview();
|
||||
}
|
||||
}
|
||||
|
||||
private void ZoneSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
@ -68,6 +77,11 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
|
||||
private void LayoutModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
RenderPreview();
|
||||
}
|
||||
|
||||
public Int32Rect[] GetZoneRects()
|
||||
{
|
||||
return _zones.ToArray();
|
||||
@ -114,9 +128,7 @@ namespace FancyZonesEditor
|
||||
RowColInfo[] colInfo = (from percent in grid.ColumnPercents
|
||||
select new RowColInfo(percent)).ToArray();
|
||||
|
||||
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
||||
|
||||
int spacing = settings.ShowSpacing ? settings.Spacing : 0;
|
||||
int spacing = grid.ShowSpacing ? grid.Spacing : 0;
|
||||
|
||||
var workArea = App.Overlay.WorkArea;
|
||||
double width = workArea.Width - (spacing * (cols + 1));
|
||||
@ -157,7 +169,7 @@ namespace FancyZonesEditor
|
||||
((col == 0) || (grid.CellChildMap[row, col - 1] != childIndex)))
|
||||
{
|
||||
// this is not a continuation of a span
|
||||
Rectangle rect = new Rectangle();
|
||||
Border rect = new Border();
|
||||
left = colInfo[col].Start;
|
||||
top = rowInfo[row].Start;
|
||||
Canvas.SetTop(rect, top);
|
||||
@ -177,9 +189,7 @@ namespace FancyZonesEditor
|
||||
|
||||
rect.Width = Math.Max(0, colInfo[maxCol].End - left);
|
||||
rect.Height = Math.Max(0, rowInfo[maxRow].End - top);
|
||||
rect.StrokeThickness = 1;
|
||||
rect.Stroke = Brushes.DarkGray;
|
||||
rect.Fill = Brushes.LightGray;
|
||||
rect.Style = (Style)FindResource("GridLayoutPreviewActualSizeStyle");
|
||||
frame.Children.Add(rect);
|
||||
_zones.Add(new Int32Rect(
|
||||
(int)left, (int)top, (int)rect.Width, (int)rect.Height));
|
||||
@ -216,8 +226,7 @@ namespace FancyZonesEditor
|
||||
Body.ColumnDefinitions.Add(def);
|
||||
}
|
||||
|
||||
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
||||
Thickness margin = new Thickness(settings.ShowSpacing ? settings.Spacing / 20 : 0);
|
||||
Thickness margin = new Thickness(grid.ShowSpacing ? grid.Spacing / 20 : 0);
|
||||
|
||||
List<int> visited = new List<int>();
|
||||
|
||||
@ -229,7 +238,7 @@ namespace FancyZonesEditor
|
||||
if (!visited.Contains(childIndex))
|
||||
{
|
||||
visited.Add(childIndex);
|
||||
Rectangle rect = new Rectangle();
|
||||
Border rect = new Border();
|
||||
Grid.SetRow(rect, row);
|
||||
Grid.SetColumn(rect, col);
|
||||
int span = 1;
|
||||
@ -251,11 +260,8 @@ namespace FancyZonesEditor
|
||||
}
|
||||
|
||||
Grid.SetColumnSpan(rect, span);
|
||||
|
||||
rect.Margin = margin;
|
||||
rect.StrokeThickness = 1;
|
||||
rect.Stroke = Brushes.DarkGray;
|
||||
rect.Fill = Brushes.LightGray;
|
||||
rect.Style = (Style)FindResource("GridLayoutPreviewStyle");
|
||||
Body.Children.Add(rect);
|
||||
}
|
||||
}
|
||||
@ -296,14 +302,21 @@ namespace FancyZonesEditor
|
||||
|
||||
foreach (Int32Rect zone in canvas.Zones)
|
||||
{
|
||||
Rectangle rect = new Rectangle();
|
||||
Border rect = new Border();
|
||||
Canvas.SetTop(rect, zone.Y);
|
||||
Canvas.SetLeft(rect, zone.X);
|
||||
rect.MinWidth = zone.Width;
|
||||
rect.MinHeight = zone.Height;
|
||||
rect.StrokeThickness = 5;
|
||||
rect.Stroke = Brushes.DarkGray;
|
||||
rect.Fill = Brushes.LightGray;
|
||||
|
||||
if (IsActualSize)
|
||||
{
|
||||
rect.Style = (Style)FindResource("CanvasLayoutPreviewActualSizeStyle");
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.Style = (Style)FindResource("CanvasLayoutPreviewStyle");
|
||||
}
|
||||
|
||||
frame.Children.Add(rect);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,40 +3,32 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using FancyZonesEditor.Models;
|
||||
using MahApps.Metro.Controls;
|
||||
using FancyZonesEditor.Utils;
|
||||
using ModernWpf.Controls;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : MetroWindow
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
// TODO: share the constants b/w C# Editor and FancyZoneLib
|
||||
public const int MaxZones = 40;
|
||||
private const int DefaultWrapPanelItemSize = 262;
|
||||
private const int SmallWrapPanelItemSize = 180;
|
||||
private const int DefaultWrapPanelItemSize = 164;
|
||||
private const int SmallWrapPanelItemSize = 164;
|
||||
private const int MinimalForDefaultWrapPanelsHeight = 900;
|
||||
|
||||
private readonly MainWindowSettingsModel _settings = ((App)Application.Current).MainWindowSettings;
|
||||
private LayoutModel _backup = null;
|
||||
|
||||
// Localizable string
|
||||
private static readonly string _defaultNamePrefix = "Custom Layout ";
|
||||
private ContentDialog _openedDialog = null;
|
||||
|
||||
public int WrapPanelItemSize { get; set; } = DefaultWrapPanelItemSize;
|
||||
|
||||
public double SettingsTextMaxWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Width / 2) - 60;
|
||||
}
|
||||
}
|
||||
|
||||
public MainWindow(bool spanZonesAcrossMonitors, Rect workArea)
|
||||
{
|
||||
InitializeComponent();
|
||||
@ -51,59 +43,84 @@ namespace FancyZonesEditor
|
||||
|
||||
if (workArea.Height < MinimalForDefaultWrapPanelsHeight || App.Overlay.MultiMonitorMode)
|
||||
{
|
||||
SizeToContent = SizeToContent.WidthAndHeight;
|
||||
WrapPanelItemSize = SmallWrapPanelItemSize;
|
||||
}
|
||||
|
||||
SizeToContent = SizeToContent.WidthAndHeight;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
DataContext = _settings;
|
||||
SetSelectedItem();
|
||||
}
|
||||
|
||||
private void MainWindow_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Escape)
|
||||
{
|
||||
OnClosing(sender, null);
|
||||
if (_openedDialog != null)
|
||||
{
|
||||
_openedDialog.Hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnClosing(sender, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DecrementZones_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_settings.ZoneCount > 1)
|
||||
var mainEditor = App.Overlay;
|
||||
if (!(mainEditor.CurrentDataContext is LayoutModel model))
|
||||
{
|
||||
_settings.ZoneCount--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (model.TemplateZoneCount > 1)
|
||||
{
|
||||
model.TemplateZoneCount--;
|
||||
}
|
||||
}
|
||||
|
||||
private void IncrementZones_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_settings.ZoneCount < MaxZones)
|
||||
var mainEditor = App.Overlay;
|
||||
if (!(mainEditor.CurrentDataContext is LayoutModel model))
|
||||
{
|
||||
_settings.ZoneCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (model.TemplateZoneCount < LayoutSettings.MaxZones)
|
||||
{
|
||||
model.TemplateZoneCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private void NewCustomLayoutButton_Click(object sender, RoutedEventArgs e)
|
||||
private void LayoutItem_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
WindowLayout window = new WindowLayout();
|
||||
window.Show();
|
||||
Hide();
|
||||
// Select(((Grid)sender).DataContext as LayoutModel);
|
||||
}
|
||||
|
||||
private void LayoutItem_Click(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
Select(((Border)sender).DataContext as LayoutModel);
|
||||
LayoutModel selectedLayoutModel = ((Grid)sender).DataContext as LayoutModel;
|
||||
Select(selectedLayoutModel);
|
||||
Apply();
|
||||
}
|
||||
|
||||
private void LayoutItem_Focused(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Ignore focus on Edit button click
|
||||
if (e.Source is Button)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Select(((Border)sender).DataContext as LayoutModel);
|
||||
}
|
||||
|
||||
private void LayoutItem_Apply(object sender, KeyEventArgs e)
|
||||
private void LayoutItem_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Return || e.Key == Key.Space)
|
||||
{
|
||||
@ -115,17 +132,39 @@ namespace FancyZonesEditor
|
||||
|
||||
private void Select(LayoutModel newSelection)
|
||||
{
|
||||
if (App.Overlay.CurrentDataContext is LayoutModel currentSelection)
|
||||
{
|
||||
currentSelection.IsSelected = false;
|
||||
}
|
||||
|
||||
newSelection.IsSelected = true;
|
||||
_settings.SetSelectedModel(newSelection);
|
||||
App.Overlay.CurrentDataContext = newSelection;
|
||||
}
|
||||
|
||||
private void EditLayout_Click(object sender, RoutedEventArgs e)
|
||||
private async void NewLayoutButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string defaultNamePrefix = FancyZonesEditor.Properties.Resources.Default_Custom_Layout_Name;
|
||||
int maxCustomIndex = 0;
|
||||
foreach (LayoutModel customModel in MainWindowSettingsModel.CustomModels)
|
||||
{
|
||||
string name = customModel.Name;
|
||||
if (name.StartsWith(defaultNamePrefix))
|
||||
{
|
||||
if (int.TryParse(name.Substring(defaultNamePrefix.Length), out int i))
|
||||
{
|
||||
if (maxCustomIndex < i)
|
||||
{
|
||||
maxCustomIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LayoutNameText.Text = defaultNamePrefix + " " + (++maxCustomIndex);
|
||||
GridLayoutRadioButton.IsChecked = true;
|
||||
GridLayoutRadioButton.Focus();
|
||||
await NewLayoutDialog.ShowAsync();
|
||||
}
|
||||
|
||||
private void DuplicateLayout_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
EditLayoutDialog.Hide();
|
||||
|
||||
var mainEditor = App.Overlay;
|
||||
if (!(mainEditor.CurrentDataContext is LayoutModel model))
|
||||
{
|
||||
@ -133,26 +172,32 @@ namespace FancyZonesEditor
|
||||
}
|
||||
|
||||
model.IsSelected = false;
|
||||
Hide();
|
||||
|
||||
bool isPredefinedLayout = MainWindowSettingsModel.IsPredefinedLayout(model);
|
||||
// make a copy
|
||||
model = model.Clone();
|
||||
mainEditor.CurrentDataContext = model;
|
||||
|
||||
if (!MainWindowSettingsModel.CustomModels.Contains(model) || isPredefinedLayout)
|
||||
string name = model.Name;
|
||||
var index = name.LastIndexOf('(');
|
||||
if (index != -1)
|
||||
{
|
||||
if (isPredefinedLayout)
|
||||
{
|
||||
// make a copy
|
||||
model = model.Clone();
|
||||
mainEditor.CurrentDataContext = model;
|
||||
}
|
||||
name = name.Remove(index);
|
||||
name = name.TrimEnd();
|
||||
}
|
||||
|
||||
int maxCustomIndex = 0;
|
||||
foreach (LayoutModel customModel in MainWindowSettingsModel.CustomModels)
|
||||
int maxCustomIndex = 0;
|
||||
foreach (LayoutModel customModel in MainWindowSettingsModel.CustomModels)
|
||||
{
|
||||
string customModelName = customModel.Name;
|
||||
if (customModelName.StartsWith(name))
|
||||
{
|
||||
string name = customModel.Name;
|
||||
if (name.StartsWith(_defaultNamePrefix))
|
||||
int openBraceIndex = customModelName.LastIndexOf('(');
|
||||
int closeBraceIndex = customModelName.LastIndexOf(')');
|
||||
if (openBraceIndex != -1 && closeBraceIndex != -1)
|
||||
{
|
||||
if (int.TryParse(name.Substring(_defaultNamePrefix.Length), out int i))
|
||||
string indexSubstring = customModelName.Substring(openBraceIndex + 1, closeBraceIndex - openBraceIndex - 1);
|
||||
|
||||
if (int.TryParse(indexSubstring, out int i))
|
||||
{
|
||||
if (maxCustomIndex < i)
|
||||
{
|
||||
@ -161,67 +206,70 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model.Name = _defaultNamePrefix + (++maxCustomIndex);
|
||||
}
|
||||
|
||||
mainEditor.OpenEditor(model);
|
||||
}
|
||||
model.Name = name + " (" + (++maxCustomIndex) + ')';
|
||||
|
||||
private void Apply_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Apply();
|
||||
model.Persist();
|
||||
|
||||
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
}
|
||||
|
||||
private void Apply()
|
||||
{
|
||||
((App)Application.Current).MainWindowSettings.ResetAppliedModel();
|
||||
|
||||
var mainEditor = App.Overlay;
|
||||
if (mainEditor.CurrentDataContext is LayoutModel model)
|
||||
{
|
||||
model.Apply();
|
||||
}
|
||||
|
||||
if (!mainEditor.MultiMonitorMode)
|
||||
{
|
||||
Close();
|
||||
_settings.SetAppliedModel(model);
|
||||
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClosing(object sender, EventArgs e)
|
||||
{
|
||||
LayoutModel.SerializeDeletedCustomZoneSets();
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
App.Overlay.CloseLayoutWindow();
|
||||
App.Current.Shutdown();
|
||||
}
|
||||
|
||||
private void OnInitialized(object sender, EventArgs e)
|
||||
private void DeleteLayout_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SetSelectedItem();
|
||||
EditLayoutDialog.Hide();
|
||||
DeleteLayout((FrameworkElement)sender);
|
||||
}
|
||||
|
||||
private void SetSelectedItem()
|
||||
private async void EditLayout_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
foreach (LayoutModel model in MainWindowSettingsModel.CustomModels)
|
||||
var dataContext = ((FrameworkElement)sender).DataContext;
|
||||
Select((LayoutModel)dataContext);
|
||||
|
||||
if (_settings.SelectedModel is GridLayoutModel grid)
|
||||
{
|
||||
if (model.IsSelected)
|
||||
{
|
||||
TemplateTab.SelectedItem = model;
|
||||
return;
|
||||
}
|
||||
_backup = new GridLayoutModel(grid);
|
||||
}
|
||||
else if (_settings.SelectedModel is CanvasLayoutModel canvas)
|
||||
{
|
||||
_backup = new CanvasLayoutModel(canvas);
|
||||
}
|
||||
|
||||
await EditLayoutDialog.ShowAsync();
|
||||
}
|
||||
|
||||
private void OnDelete(object sender, RoutedEventArgs e)
|
||||
private void EditZones_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LayoutModel model = ((FrameworkElement)sender).DataContext as LayoutModel;
|
||||
if (model.IsSelected)
|
||||
EditLayoutDialog.Hide();
|
||||
var mainEditor = App.Overlay;
|
||||
if (!(mainEditor.CurrentDataContext is LayoutModel model))
|
||||
{
|
||||
SetSelectedItem();
|
||||
return;
|
||||
}
|
||||
|
||||
model.Delete();
|
||||
_settings.SetSelectedModel(model);
|
||||
|
||||
Hide();
|
||||
mainEditor.OpenEditor(model);
|
||||
}
|
||||
|
||||
private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
|
||||
@ -239,32 +287,129 @@ namespace FancyZonesEditor
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CloseButton_Click(object sender, RoutedEventArgs e)
|
||||
private void NewLayoutDialog_PrimaryButtonClick(ModernWpf.Controls.ContentDialog sender, ModernWpf.Controls.ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
this.Close();
|
||||
LayoutModel selectedLayoutModel;
|
||||
|
||||
if (GridLayoutRadioButton.IsChecked == true)
|
||||
{
|
||||
GridLayoutModel gridModel = new GridLayoutModel(LayoutNameText.Text, LayoutType.Custom)
|
||||
{
|
||||
Rows = 1,
|
||||
RowPercents = new List<int>(1) { GridLayoutModel.GridMultiplier },
|
||||
};
|
||||
selectedLayoutModel = gridModel;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedLayoutModel = new CanvasLayoutModel(LayoutNameText.Text, LayoutType.Custom)
|
||||
{
|
||||
TemplateZoneCount = 0,
|
||||
};
|
||||
}
|
||||
|
||||
selectedLayoutModel.InitTemplateZones();
|
||||
|
||||
App.Overlay.CurrentDataContext = selectedLayoutModel;
|
||||
var mainEditor = App.Overlay;
|
||||
Hide();
|
||||
mainEditor.OpenEditor(selectedLayoutModel);
|
||||
}
|
||||
|
||||
private void Reset_Click(object sender, RoutedEventArgs e)
|
||||
// This is required to fix a WPF rendering bug when using custom chrome
|
||||
private void OnContentRendered(object sender, EventArgs e)
|
||||
{
|
||||
var overlay = App.Overlay;
|
||||
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
if (overlay.CurrentDataContext is LayoutModel model)
|
||||
private void MonitorItem_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Return || e.Key == Key.Space)
|
||||
{
|
||||
model.IsSelected = false;
|
||||
model.IsApplied = false;
|
||||
monitorViewModel.SelectCommand.Execute((MonitorInfoModel)(sender as Border).DataContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void MonitorItem_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
monitorViewModel.SelectCommand.Execute((MonitorInfoModel)(sender as Border).DataContext);
|
||||
}
|
||||
|
||||
// EditLayout: Cancel changes
|
||||
private void EditLayoutDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
// restore model properties from settings
|
||||
_settings.RestoreSelectedModel(_backup);
|
||||
_backup = null;
|
||||
|
||||
Select(_settings.AppliedModel);
|
||||
}
|
||||
|
||||
// EditLayout: Save changes
|
||||
private void EditLayoutDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
var mainEditor = App.Overlay;
|
||||
if (!(mainEditor.CurrentDataContext is LayoutModel model))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
overlay.CurrentLayoutSettings.ZonesetUuid = settings.BlankModel.Uuid;
|
||||
overlay.CurrentLayoutSettings.Type = LayoutType.Blank;
|
||||
overlay.CurrentDataContext = settings.BlankModel;
|
||||
_backup = null;
|
||||
|
||||
App.FancyZonesEditorIO.SerializeAppliedLayouts();
|
||||
|
||||
if (!overlay.MultiMonitorMode)
|
||||
// update current settings
|
||||
if (model == _settings.AppliedModel)
|
||||
{
|
||||
Close();
|
||||
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
||||
}
|
||||
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
|
||||
// reset selected model
|
||||
Select(_settings.AppliedModel);
|
||||
}
|
||||
|
||||
private async void DeleteLayout(FrameworkElement element)
|
||||
{
|
||||
var dialog = new ModernWpf.Controls.ContentDialog()
|
||||
{
|
||||
Title = FancyZonesEditor.Properties.Resources.Are_You_Sure,
|
||||
Content = FancyZonesEditor.Properties.Resources.Are_You_Sure_Description,
|
||||
PrimaryButtonText = FancyZonesEditor.Properties.Resources.Delete,
|
||||
SecondaryButtonText = FancyZonesEditor.Properties.Resources.Cancel,
|
||||
};
|
||||
|
||||
var result = await dialog.ShowAsync();
|
||||
if (result == ContentDialogResult.Primary)
|
||||
{
|
||||
LayoutModel model = element.DataContext as LayoutModel;
|
||||
|
||||
if (model == _settings.AppliedModel)
|
||||
{
|
||||
_settings.SetAppliedModel(_settings.BlankModel);
|
||||
Select(_settings.BlankModel);
|
||||
}
|
||||
|
||||
foreach (var monitor in App.Overlay.Monitors)
|
||||
{
|
||||
if (monitor.Settings.ZonesetUuid == model.Uuid)
|
||||
{
|
||||
App.Overlay.SetLayoutSettings(monitor, _settings.BlankModel);
|
||||
}
|
||||
}
|
||||
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
model.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
private void Dialog_Opened(ContentDialog sender, ContentDialogOpenedEventArgs args)
|
||||
{
|
||||
_openedDialog = sender;
|
||||
}
|
||||
|
||||
private void Dialog_Closed(ContentDialog sender, ContentDialogClosedEventArgs args)
|
||||
{
|
||||
_openedDialog = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using FancyZonesEditor.Utils;
|
||||
|
||||
|
@ -13,7 +13,6 @@ namespace FancyZonesEditor
|
||||
public class Overlay
|
||||
{
|
||||
private MainWindow _mainWindow;
|
||||
|
||||
private LayoutPreview _layoutPreview;
|
||||
private UserControl _editor;
|
||||
|
||||
@ -28,7 +27,7 @@ namespace FancyZonesEditor
|
||||
return Monitors[CurrentDesktop].Device.WorkAreaRect;
|
||||
}
|
||||
|
||||
return default(Rect);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,7 +53,7 @@ namespace FancyZonesEditor
|
||||
return Monitors[CurrentDesktop].Window;
|
||||
}
|
||||
|
||||
return default(Window);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,14 +99,13 @@ namespace FancyZonesEditor
|
||||
return;
|
||||
}
|
||||
|
||||
var prevSettings = CurrentLayoutSettings;
|
||||
_currentDesktop = value;
|
||||
|
||||
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
||||
if (settings != null)
|
||||
{
|
||||
settings.ResetAppliedModel();
|
||||
settings.UpdateDesktopDependantProperties(prevSettings);
|
||||
settings.SetAppliedModel(null);
|
||||
settings.UpdateDefaultModels();
|
||||
}
|
||||
|
||||
Update();
|
||||
@ -130,8 +128,8 @@ namespace FancyZonesEditor
|
||||
|
||||
if (_spanZonesAcrossMonitors)
|
||||
{
|
||||
Rect workArea = default(Rect);
|
||||
Rect bounds = default(Rect);
|
||||
Rect workArea = default;
|
||||
Rect bounds = default;
|
||||
|
||||
foreach (Monitor monitor in Monitors)
|
||||
{
|
||||
@ -174,7 +172,7 @@ namespace FancyZonesEditor
|
||||
_layoutPreview = new LayoutPreview
|
||||
{
|
||||
IsActualSize = true,
|
||||
Opacity = 0.5,
|
||||
Opacity = 1,
|
||||
};
|
||||
|
||||
ShowLayout();
|
||||
@ -201,6 +199,30 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLayoutSettings(Monitor monitor, LayoutModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.Settings.ZonesetUuid = model.Uuid;
|
||||
monitor.Settings.Type = model.Type;
|
||||
monitor.Settings.SensitivityRadius = model.SensitivityRadius;
|
||||
monitor.Settings.ZoneCount = model.TemplateZoneCount;
|
||||
|
||||
if (model is GridLayoutModel grid)
|
||||
{
|
||||
monitor.Settings.ShowSpacing = grid.ShowSpacing;
|
||||
monitor.Settings.Spacing = grid.Spacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
monitor.Settings.ShowSpacing = false;
|
||||
monitor.Settings.Spacing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenEditor(LayoutModel model)
|
||||
{
|
||||
_layoutPreview = null;
|
||||
@ -216,11 +238,10 @@ namespace FancyZonesEditor
|
||||
CurrentLayoutWindow.Content = _editor;
|
||||
|
||||
EditorWindow window;
|
||||
bool isGrid = false;
|
||||
|
||||
if (model is GridLayoutModel)
|
||||
{
|
||||
window = new GridEditorWindow();
|
||||
isGrid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -230,14 +251,6 @@ namespace FancyZonesEditor
|
||||
window.Owner = Monitors[App.Overlay.CurrentDesktop].Window;
|
||||
window.DataContext = model;
|
||||
window.Show();
|
||||
|
||||
if (isGrid)
|
||||
{
|
||||
(window as GridEditorWindow).NameTextBox().Focus();
|
||||
}
|
||||
|
||||
window.LeftWindowCommands = null;
|
||||
window.RightWindowCommands = null;
|
||||
}
|
||||
|
||||
public void CloseEditor()
|
||||
@ -246,7 +259,7 @@ namespace FancyZonesEditor
|
||||
_layoutPreview = new LayoutPreview
|
||||
{
|
||||
IsActualSize = true,
|
||||
Opacity = 0.5,
|
||||
Opacity = 1,
|
||||
};
|
||||
|
||||
CurrentLayoutWindow.Content = _layoutPreview;
|
||||
@ -318,8 +331,6 @@ namespace FancyZonesEditor
|
||||
_mainWindow.ShowActivated = true;
|
||||
_mainWindow.Topmost = true;
|
||||
_mainWindow.Show();
|
||||
_mainWindow.LeftWindowCommands = null;
|
||||
_mainWindow.RightWindowCommands = null;
|
||||
|
||||
// window is set to topmost to make sure it shows on top of PowerToys settings page
|
||||
// we can reset topmost flag now
|
||||
|
@ -78,6 +78,33 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Apply layout.
|
||||
/// </summary>
|
||||
public static string Apply_Layout {
|
||||
get {
|
||||
return ResourceManager.GetString("Apply_Layout", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Are you sure?.
|
||||
/// </summary>
|
||||
public static string Are_You_Sure {
|
||||
get {
|
||||
return ResourceManager.GetString("Are_You_Sure", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Are you sure you want to delete this layout?.
|
||||
/// </summary>
|
||||
public static string Are_You_Sure_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Are_You_Sure_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cancel.
|
||||
/// </summary>
|
||||
@ -97,7 +124,7 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Choose your layout for this desktop.
|
||||
/// Looks up a localized string similar to Choose the layout for this desktop.
|
||||
/// </summary>
|
||||
public static string Choose_Layout {
|
||||
get {
|
||||
@ -105,6 +132,15 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Choose layout type.
|
||||
/// </summary>
|
||||
public static string Choose_layout_type {
|
||||
get {
|
||||
return ResourceManager.GetString("Choose_layout_type", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Close.
|
||||
/// </summary>
|
||||
@ -132,6 +168,33 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create.
|
||||
/// </summary>
|
||||
public static string Create {
|
||||
get {
|
||||
return ResourceManager.GetString("Create", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create custom layout.
|
||||
/// </summary>
|
||||
public static string Create_Custom_From_Template {
|
||||
get {
|
||||
return ResourceManager.GetString("Create_Custom_From_Template", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create new layout.
|
||||
/// </summary>
|
||||
public static string Create_new_layout {
|
||||
get {
|
||||
return ResourceManager.GetString("Create_new_layout", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Custom.
|
||||
/// </summary>
|
||||
@ -142,7 +205,7 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create new custom.
|
||||
/// Looks up a localized string similar to Custom layout.
|
||||
/// </summary>
|
||||
public static string Custom_Layout_Create_New {
|
||||
get {
|
||||
@ -160,20 +223,29 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Delete custom layout.
|
||||
/// Looks up a localized string similar to Custom layout.
|
||||
/// </summary>
|
||||
public static string Custom_Layout_Delete_Button {
|
||||
public static string Default_Custom_Layout_Name {
|
||||
get {
|
||||
return ResourceManager.GetString("Custom_Layout_Delete_Button", resourceCulture);
|
||||
return ResourceManager.GetString("Default_Custom_Layout_Name", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Custom table layout creator.
|
||||
/// Looks up a localized string similar to Delete.
|
||||
/// </summary>
|
||||
public static string Custom_Table_Layout {
|
||||
public static string Delete {
|
||||
get {
|
||||
return ResourceManager.GetString("Custom_Table_Layout", resourceCulture);
|
||||
return ResourceManager.GetString("Delete", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Delete zone.
|
||||
/// </summary>
|
||||
public static string Delete_Zone {
|
||||
get {
|
||||
return ResourceManager.GetString("Delete_Zone", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,11 +259,38 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit selected layout.
|
||||
/// Looks up a localized string similar to Duplicate.
|
||||
/// </summary>
|
||||
public static string Edit_Selected_Layout {
|
||||
public static string Duplicate {
|
||||
get {
|
||||
return ResourceManager.GetString("Edit_Selected_Layout", resourceCulture);
|
||||
return ResourceManager.GetString("Duplicate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit.
|
||||
/// </summary>
|
||||
public static string Edit {
|
||||
get {
|
||||
return ResourceManager.GetString("Edit", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit layout.
|
||||
/// </summary>
|
||||
public static string Edit_Layout {
|
||||
get {
|
||||
return ResourceManager.GetString("Edit_Layout", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit zones.
|
||||
/// </summary>
|
||||
public static string Edit_zones {
|
||||
get {
|
||||
return ResourceManager.GetString("Edit_zones", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,6 +375,33 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 'zones-settings.json' contains malformed data..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Zones_Settings_Malformed_Data {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_Parsing_Zones_Settings_Malformed_Data", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Editor settings parsing error..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Zones_Settings_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_Parsing_Zones_Settings_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Would you like to continue? Malformed data will be lost..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Zones_Settings_User_Choice {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_Parsing_Zones_Settings_User_Choice", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error persisting custom layout.
|
||||
/// </summary>
|
||||
@ -330,6 +456,60 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create layouts that have overlapping zones.
|
||||
/// </summary>
|
||||
public static string Layout_Canvas_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Layout_Canvas_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Canvas.
|
||||
/// </summary>
|
||||
public static string Layout_Canvas_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("Layout_Canvas_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create layouts that are horizontally or vertically stacked.
|
||||
/// </summary>
|
||||
public static string Layout_Grid_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Layout_Grid_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Grid.
|
||||
/// </summary>
|
||||
public static string Layout_Grid_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("Layout_Grid_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Merge zones.
|
||||
/// </summary>
|
||||
public static string Merge_zones {
|
||||
get {
|
||||
return ResourceManager.GetString("Merge_zones", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Monitor.
|
||||
/// </summary>
|
||||
public static string Monitor {
|
||||
get {
|
||||
return ResourceManager.GetString("Monitor", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Name.
|
||||
/// </summary>
|
||||
@ -340,7 +520,17 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Note: Hold down Shift Key to change orientation of splitter. To merge zones, select the zones and click "merge"..
|
||||
/// Looks up a localized string similar to Create or duplicate a layout to get started.
|
||||
/// </summary>
|
||||
public static string No_Custom_Layouts_Message {
|
||||
get {
|
||||
return ResourceManager.GetString("No_Custom_Layouts_Message", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Hold down Shift key to change orientation of splitter.
|
||||
///To merge zones, select the zones and click "merge"..
|
||||
/// </summary>
|
||||
public static string Note_Custom_Table {
|
||||
get {
|
||||
@ -348,6 +538,15 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Number of zones.
|
||||
/// </summary>
|
||||
public static string NumberOfZones {
|
||||
get {
|
||||
return ResourceManager.GetString("NumberOfZones", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Reset layout.
|
||||
/// </summary>
|
||||
@ -358,7 +557,16 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Save and apply.
|
||||
/// Looks up a localized string similar to Save.
|
||||
/// </summary>
|
||||
public static string Save {
|
||||
get {
|
||||
return ResourceManager.GetString("Save", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Save & apply.
|
||||
/// </summary>
|
||||
public static string Save_Apply {
|
||||
get {
|
||||
@ -366,6 +574,15 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Template settings.
|
||||
/// </summary>
|
||||
public static string Settings {
|
||||
get {
|
||||
return ResourceManager.GetString("Settings", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show space around zones.
|
||||
/// </summary>
|
||||
@ -385,20 +602,11 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Custom tab selected, press ctrl + tab to switch to Templates.
|
||||
/// Looks up a localized string similar to No layout.
|
||||
/// </summary>
|
||||
public static string Tab_Item_Custom {
|
||||
public static string Template_Layout_Blank {
|
||||
get {
|
||||
return ResourceManager.GetString("Tab_Item_Custom", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Templates tab selected, press ctrl + tab to switch to Custom.
|
||||
/// </summary>
|
||||
public static string Tab_Item_Templates {
|
||||
get {
|
||||
return ResourceManager.GetString("Tab_Item_Templates", resourceCulture);
|
||||
return ResourceManager.GetString("Template_Layout_Blank", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,9 +132,6 @@
|
||||
<data name="Grid_Layout_Editor" xml:space="preserve">
|
||||
<value>Grid layout editor</value>
|
||||
</data>
|
||||
<data name="Choose_Layout" xml:space="preserve">
|
||||
<value>Choose your layout for this desktop</value>
|
||||
</data>
|
||||
<data name="Crash_Report_Message_Box_Text_Part1" xml:space="preserve">
|
||||
<value>Error logged to </value>
|
||||
</data>
|
||||
@ -147,14 +144,11 @@
|
||||
<data name="Custom_Layout_Creator" xml:space="preserve">
|
||||
<value>Custom layout creator</value>
|
||||
</data>
|
||||
<data name="Custom_Table_Layout" xml:space="preserve">
|
||||
<value>Custom table layout creator</value>
|
||||
</data>
|
||||
<data name="Distance_adjacent_zones" xml:space="preserve">
|
||||
<value>Distance to highlight adjacent zones</value>
|
||||
</data>
|
||||
<data name="Edit_Selected_Layout" xml:space="preserve">
|
||||
<value>Edit selected layout</value>
|
||||
<data name="Edit_Layout" xml:space="preserve">
|
||||
<value>Edit layout</value>
|
||||
</data>
|
||||
<data name="Fancy_Zones_Editor_App_Title" xml:space="preserve">
|
||||
<value>FancyZones Editor</value>
|
||||
@ -166,10 +160,11 @@
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="Note_Custom_Table" xml:space="preserve">
|
||||
<value>Note: Hold down Shift Key to change orientation of splitter. To merge zones, select the zones and click "merge".</value>
|
||||
<value>Hold down Shift key to change orientation of splitter.
|
||||
To merge zones, select the zones and click "merge".</value>
|
||||
</data>
|
||||
<data name="Save_Apply" xml:space="preserve">
|
||||
<value>Save and apply</value>
|
||||
<value>Save & apply</value>
|
||||
</data>
|
||||
<data name="Show_Space_Zones" xml:space="preserve">
|
||||
<value>Show space around zones</value>
|
||||
@ -186,13 +181,6 @@
|
||||
<data name="Zone_Count_Increment" xml:space="preserve">
|
||||
<value>Increment number of zones in template layout</value>
|
||||
</data>
|
||||
<data name="Custom_Layout_Delete_Button" xml:space="preserve">
|
||||
<value>Delete custom layout</value>
|
||||
</data>
|
||||
<data name="Custom_Layout_Create_New" xml:space="preserve">
|
||||
<value>Create new custom</value>
|
||||
<comment>As in Create new custom layout</comment>
|
||||
</data>
|
||||
<data name="Error_Invalid_Arguments" xml:space="preserve">
|
||||
<value>FancyZones Editor arguments are invalid.</value>
|
||||
</data>
|
||||
@ -220,12 +208,6 @@
|
||||
<data name="Template_Layout_Rows" xml:space="preserve">
|
||||
<value>Rows</value>
|
||||
</data>
|
||||
<data name="Tab_Item_Custom" xml:space="preserve">
|
||||
<value>Custom tab selected, press ctrl + tab to switch to Templates</value>
|
||||
</data>
|
||||
<data name="Tab_Item_Templates" xml:space="preserve">
|
||||
<value>Templates tab selected, press ctrl + tab to switch to Custom</value>
|
||||
</data>
|
||||
<data name="Close" xml:space="preserve">
|
||||
<value>Close</value>
|
||||
</data>
|
||||
@ -257,4 +239,99 @@
|
||||
<value>Reset layout</value>
|
||||
<comment>as in Reset to a blank value</comment>
|
||||
</data>
|
||||
<data name="Choose_Layout" xml:space="preserve">
|
||||
<value>Choose the layout for this desktop</value>
|
||||
</data>
|
||||
<data name="Choose_layout_type" xml:space="preserve">
|
||||
<value>Choose layout type</value>
|
||||
<comment>Dialog header that allows the user to select a specific layout type</comment>
|
||||
</data>
|
||||
<data name="Create" xml:space="preserve">
|
||||
<value>Create</value>
|
||||
<comment>Button label that creates a new layout</comment>
|
||||
</data>
|
||||
<data name="Create_new_layout" xml:space="preserve">
|
||||
<value>Create new layout</value>
|
||||
<comment>Button label that allows the user to create a new layout</comment>
|
||||
</data>
|
||||
<data name="Custom_Layout_Create_New" xml:space="preserve">
|
||||
<value>Custom layout</value>
|
||||
</data>
|
||||
<data name="Delete" xml:space="preserve">
|
||||
<value>Delete</value>
|
||||
<comment>Context menu label that allows the user duplicate a layout</comment>
|
||||
</data>
|
||||
<data name="Duplicate" xml:space="preserve">
|
||||
<value>Duplicate</value>
|
||||
<comment>Context menu label that allows the user duplicate a layout</comment>
|
||||
</data>
|
||||
<data name="Edit" xml:space="preserve">
|
||||
<value>Edit</value>
|
||||
<comment>Context menu label that allows the user edit a layout</comment>
|
||||
</data>
|
||||
<data name="Layout_Canvas_Description" xml:space="preserve">
|
||||
<value>Create layouts that have overlapping zones</value>
|
||||
</data>
|
||||
<data name="Layout_Canvas_Title" xml:space="preserve">
|
||||
<value>Canvas</value>
|
||||
</data>
|
||||
<data name="Layout_Grid_Description" xml:space="preserve">
|
||||
<value>Create layouts that are horizontally or vertically stacked</value>
|
||||
</data>
|
||||
<data name="Layout_Grid_Title" xml:space="preserve">
|
||||
<value>Grid</value>
|
||||
</data>
|
||||
<data name="Merge_zones" xml:space="preserve">
|
||||
<value>Merge zones</value>
|
||||
<comment>Button label that allows the user to merge 2 or more zones together</comment>
|
||||
</data>
|
||||
<data name="Monitor" xml:space="preserve">
|
||||
<value>Monitor</value>
|
||||
</data>
|
||||
<data name="Settings" xml:space="preserve">
|
||||
<value>Template settings</value>
|
||||
</data>
|
||||
<data name="Are_You_Sure" xml:space="preserve">
|
||||
<value>Are you sure?</value>
|
||||
</data>
|
||||
<data name="Are_You_Sure_Description" xml:space="preserve">
|
||||
<value>Are you sure you want to delete this layout?</value>
|
||||
</data>
|
||||
<data name="Edit_zones" xml:space="preserve">
|
||||
<value>Edit zones</value>
|
||||
</data>
|
||||
<data name="No_Custom_Layouts_Message" xml:space="preserve">
|
||||
<value>Create or duplicate a layout to get started</value>
|
||||
</data>
|
||||
<data name="Delete_Zone" xml:space="preserve">
|
||||
<value>Delete zone</value>
|
||||
<comment>A tooltip on a button that allows the user to delete a zone</comment>
|
||||
</data>
|
||||
<data name="Error_Parsing_Zones_Settings_Malformed_Data" xml:space="preserve">
|
||||
<value>'zones-settings.json' contains malformed data.</value>
|
||||
</data>
|
||||
<data name="Error_Parsing_Zones_Settings_Title" xml:space="preserve">
|
||||
<value>Editor settings parsing error.</value>
|
||||
</data>
|
||||
<data name="Error_Parsing_Zones_Settings_User_Choice" xml:space="preserve">
|
||||
<value>Would you like to continue? Malformed data will be lost.</value>
|
||||
</data>
|
||||
<data name="Apply_Layout" xml:space="preserve">
|
||||
<value>Apply layout</value>
|
||||
</data>
|
||||
<data name="Save" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="NumberOfZones" xml:space="preserve">
|
||||
<value>Number of zones</value>
|
||||
</data>
|
||||
<data name="Template_Layout_Blank" xml:space="preserve">
|
||||
<value>No layout</value>
|
||||
</data>
|
||||
<data name="Create_Custom_From_Template" xml:space="preserve">
|
||||
<value>Create custom layout</value>
|
||||
</data>
|
||||
<data name="Default_Custom_Layout_Name" xml:space="preserve">
|
||||
<value>Custom layout</value>
|
||||
</data>
|
||||
</root>
|
@ -0,0 +1,93 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor.Styles">
|
||||
|
||||
<Style x:Key="LayoutTypeRadioButtonStyle" TargetType="RadioButton">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Background" Value="{DynamicResource RadioButtonBackground}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource RadioButtonForeground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrush}" />
|
||||
<Setter Property="Padding" Value="12" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Top" />
|
||||
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="MinWidth" Value="120" />
|
||||
<Setter Property="FocusVisualStyle" Value="{DynamicResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
|
||||
<Setter Property="ui:FocusVisualHelper.UseSystemFocusVisuals" Value="{DynamicResource UseSystemFocusVisuals}" />
|
||||
<Setter Property="ui:FocusVisualHelper.FocusVisualMargin" Value="0" />
|
||||
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="RadioButton">
|
||||
<Border
|
||||
x:Name="RootGrid"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="2"
|
||||
|
||||
SnapsToDevicePixels="True">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CheckStates">
|
||||
<VisualState x:Name="Checked">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="CheckGlyph"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="1"
|
||||
Duration="0" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Unchecked" />
|
||||
<VisualState x:Name="Indeterminate" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<Grid>
|
||||
|
||||
<Border x:Name="CheckGlyph"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
UseLayoutRounding="False"
|
||||
Opacity="0"
|
||||
CornerRadius="2"
|
||||
BorderThickness="2"
|
||||
BorderBrush="{DynamicResource SystemControlBackgroundAccentBrush}" />
|
||||
|
||||
<ui:ContentPresenterEx x:Name="ContentPresenter"
|
||||
TextElement.Foreground="{TemplateBinding Foreground}"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Grid.Column="1"
|
||||
TextWrapping="Wrap"
|
||||
Focusable="False"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="ContentPresenter"
|
||||
Property="Foreground"
|
||||
Value="{DynamicResource RadioButtonForegroundPointerOver}" />
|
||||
<Setter TargetName="CheckGlyph" Property="Opacity" Value="0.6" />
|
||||
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="ContentPresenter" Property="Foreground" Value="{DynamicResource RadioButtonForegroundPressed}" />
|
||||
<Setter TargetName="RootGrid" Property="Background" Value="{DynamicResource RadioButtonBackgroundPressed}" />
|
||||
<Setter TargetName="RootGrid" Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrushPressed}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="ContentPresenter" Property="Foreground" Value="{DynamicResource RadioButtonForegroundDisabled}" />
|
||||
<Setter TargetName="RootGrid" Property="Background" Value="{DynamicResource RadioButtonBackgroundDisabled}" />
|
||||
<Setter TargetName="RootGrid" Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrushDisabled}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
@ -0,0 +1,41 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor.Styles">
|
||||
|
||||
<Style x:Key="GridLayoutPreviewStyle" TargetType="Border">
|
||||
<Setter Property="Background" Value="{DynamicResource LayoutPreviewZoneBackgroundBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource LayoutItemBackgroundBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="GridLayoutPreviewActualSizeStyle"
|
||||
TargetType="Border">
|
||||
<Setter Property="Background" Value="{DynamicResource LayoutPreviewZoneBackgroundBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource LayoutPreviewZoneBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius"
|
||||
Value="4" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="CanvasLayoutPreviewStyle"
|
||||
TargetType="Border">
|
||||
<Setter Property="Background" Value="{DynamicResource LayoutPreviewZoneBackgroundBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource LayoutItemBackgroundBrush}" />
|
||||
<Setter Property="BorderThickness" Value="10" />
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="CanvasLayoutPreviewActualSizeStyle"
|
||||
TargetType="Border">
|
||||
<Setter Property="Background" Value="{DynamicResource LayoutPreviewZoneBackgroundBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource LayoutPreviewZoneBorderBrush}" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="CornerRadius"
|
||||
Value="4" />
|
||||
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
@ -0,0 +1,27 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">Dark.Accent1</system:String>
|
||||
<system:String x:Key="Theme.Origin">PowerToysRun</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent1 (Dark)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">Dark</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent1</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">Black</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF242424" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF1c1c1c" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFFFFFFF" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF9a9a9a" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#88000000" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundBrush" Color="#FF3A3A3A" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundPointerOverBrush" Color="#FF333333" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBackgroundBrush" Color="#BF1b1b1b" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewBackgroundBrush" Color="#331B1B1B" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBorderBrush" Color="#FF5a5a5a" />
|
||||
<SolidColorBrush x:Key="CanvasZoneBackgroundBrush" Color="#BF1b1b1b"/>
|
||||
<SolidColorBrush x:Key="GridZoneBackgroundBrush" Color="#E51b1b1b" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,27 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">HighContrast.Accent2</system:String>
|
||||
<system:String x:Key="Theme.Origin">PowerToysRun</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent2 (HighContrast)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent2</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF242424" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF1c1c1c" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffff00" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF00ff00" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#88000000" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundBrush" Color="#FF2b2b2b" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundPointerOverBrush" Color="#FF333333" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBackgroundBrush" Color="#BF1b1b1b" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewBackgroundBrush" Color="#331B1B1B" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBorderBrush" Color="#FF1b1b1b" />
|
||||
<SolidColorBrush x:Key="CanvasZoneBackgroundBrush" Color="#BF1b1b1b" />
|
||||
<SolidColorBrush x:Key="GridZoneBackgroundBrush" Color="#E51b1b1b" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,27 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">HighContrast.Accent3</system:String>
|
||||
<system:String x:Key="Theme.Origin">PowerToysRun</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent3 (HighContrast)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent3</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF242424" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF1c1c1c" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffff00" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FFc0c0c0" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#88000000" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundBrush" Color="#FF2b2b2b" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundPointerOverBrush" Color="#FF333333" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBackgroundBrush" Color="#BF1b1b1b" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewBackgroundBrush" Color="#331B1B1B" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBorderBrush" Color="#FF1b1b1b" />
|
||||
<SolidColorBrush x:Key="CanvasZoneBackgroundBrush" Color="#BF1b1b1b" />
|
||||
<SolidColorBrush x:Key="GridZoneBackgroundBrush" Color="#E51b1b1b" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,27 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">HighContrast.Accent4</system:String>
|
||||
<system:String x:Key="Theme.Origin">PowerToysRun</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent4 (HighContrast)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent4</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF242424" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF1c1c1c" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffffff" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF1aebff" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#88000000" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundBrush" Color="#FF3A3A3A" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundPointerOverBrush" Color="#FF333333" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBackgroundBrush" Color="#BF1b1b1b" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewBackgroundBrush" Color="#331B1B1B" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBorderBrush" Color="#FF5a5a5a" />
|
||||
<SolidColorBrush x:Key="CanvasZoneBackgroundBrush" Color="#BF1b1b1b" />
|
||||
<SolidColorBrush x:Key="GridZoneBackgroundBrush" Color="#E51b1b1b" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,27 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">HighContrast.Accent5</system:String>
|
||||
<system:String x:Key="Theme.Origin">PowerToysRun</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent5 (HighContrast)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent5</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FFf9f9f9" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FFeeeeee" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FFF3F3F3" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF000000" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF37006e" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#88FFFFFF" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF949494" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundBrush" Color="#FFffffff" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundPointerOverBrush" Color="#FFf2f2f2" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBackgroundBrush" Color="#88cccccc" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewBackgroundBrush" Color="#19949494" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBorderBrush" Color="#9c9c9c" />
|
||||
<SolidColorBrush x:Key="CanvasZoneBackgroundBrush" Color="#BFffffff" />
|
||||
<SolidColorBrush x:Key="GridZoneBackgroundBrush" Color="#E5ffffff" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,27 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">Light.Accent1</system:String>
|
||||
<system:String x:Key="Theme.Origin">PowerToysRun</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent1 (Light)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">Light</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent1</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FFF9F9F9" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FFeeeeee" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FFF3F3F3" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF000000" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF949494" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#88FFFFFF" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF949494" />
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundBrush" Color="#FFffffff"/>
|
||||
<SolidColorBrush x:Key="LayoutItemBackgroundPointerOverBrush" Color="#FFf2f2f2" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBackgroundBrush" Color="#88cccccc"/>
|
||||
<SolidColorBrush x:Key="LayoutPreviewBackgroundBrush" Color="#19949494" />
|
||||
<SolidColorBrush x:Key="LayoutPreviewZoneBorderBrush" Color="#9c9c9c" />
|
||||
<SolidColorBrush x:Key="CanvasZoneBackgroundBrush" Color="#BFffffff"/>
|
||||
<SolidColorBrush x:Key="GridZoneBackgroundBrush" Color="#E5ffffff" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,24 @@
|
||||
// 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.Collections.Generic;
|
||||
using ControlzEx.Theming;
|
||||
|
||||
namespace FancyZonesEditor.Utils
|
||||
{
|
||||
public class CustomLibraryThemeProvider : LibraryThemeProvider
|
||||
{
|
||||
public static readonly CustomLibraryThemeProvider DefaultInstance = new CustomLibraryThemeProvider();
|
||||
|
||||
public CustomLibraryThemeProvider()
|
||||
: base(true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void FillColorSchemeValues(Dictionary<string, string> values, RuntimeThemeColorValues colorValues)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,200 @@
|
||||
// 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.Linq;
|
||||
using System.Windows;
|
||||
using ControlzEx.Theming;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace FancyZonesEditor.Utils
|
||||
{
|
||||
public class ThemeManager : IDisposable
|
||||
{
|
||||
private readonly Application _app;
|
||||
private const string LightTheme = "Light.Accent1";
|
||||
private const string DarkTheme = "Dark.Accent1";
|
||||
private const string HighContrastOneTheme = "HighContrast.Accent2";
|
||||
private const string HighContrastTwoTheme = "HighContrast.Accent3";
|
||||
private const string HighContrastBlackTheme = "HighContrast.Accent4";
|
||||
private const string HighContrastWhiteTheme = "HighContrast.Accent5";
|
||||
|
||||
private Theme currentTheme;
|
||||
private bool _disposed;
|
||||
|
||||
public event ThemeChangedHandler ThemeChanged;
|
||||
|
||||
public ThemeManager(Application app)
|
||||
{
|
||||
_app = app;
|
||||
|
||||
Uri highContrastOneThemeUri = new Uri("pack://application:,,,/Themes/HighContrast1.xaml");
|
||||
Uri highContrastTwoThemeUri = new Uri("pack://application:,,,/Themes/HighContrast2.xaml");
|
||||
Uri highContrastBlackThemeUri = new Uri("pack://application:,,,/Themes/HighContrastWhite.xaml");
|
||||
Uri highContrastWhiteThemeUri = new Uri("pack://application:,,,/Themes/HighContrastBlack.xaml");
|
||||
Uri lightThemeUri = new Uri("pack://application:,,,/Themes/Light.xaml");
|
||||
Uri darkThemeUri = new Uri("pack://application:,,,/Themes/Dark.xaml");
|
||||
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new LibraryTheme(
|
||||
highContrastOneThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new LibraryTheme(
|
||||
highContrastTwoThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new LibraryTheme(
|
||||
highContrastBlackThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new LibraryTheme(
|
||||
highContrastWhiteThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new LibraryTheme(
|
||||
lightThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new LibraryTheme(
|
||||
darkThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
|
||||
ResetTheme();
|
||||
ControlzEx.Theming.ThemeManager.Current.ThemeSyncMode = ThemeSyncMode.SyncWithAppMode;
|
||||
ControlzEx.Theming.ThemeManager.Current.ThemeChanged += Current_ThemeChanged;
|
||||
SystemParameters.StaticPropertyChanged += SystemParameters_StaticPropertyChanged;
|
||||
}
|
||||
|
||||
private void SystemParameters_StaticPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(SystemParameters.HighContrast))
|
||||
{
|
||||
ResetTheme();
|
||||
}
|
||||
}
|
||||
|
||||
public Theme GetCurrentTheme()
|
||||
{
|
||||
return currentTheme;
|
||||
}
|
||||
|
||||
private static Theme GetHighContrastBaseType()
|
||||
{
|
||||
string registryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes";
|
||||
string theme = (string)Registry.GetValue(registryKey, "CurrentTheme", string.Empty);
|
||||
theme = theme.Split('\\').Last().Split('.').First().ToString();
|
||||
|
||||
switch (theme)
|
||||
{
|
||||
case "hc1":
|
||||
return Theme.HighContrastOne;
|
||||
case "hc2":
|
||||
return Theme.HighContrastTwo;
|
||||
case "hcwhite":
|
||||
return Theme.HighContrastWhite;
|
||||
case "hcblack":
|
||||
return Theme.HighContrastBlack;
|
||||
default:
|
||||
return Theme.None;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetTheme()
|
||||
{
|
||||
if (SystemParameters.HighContrast)
|
||||
{
|
||||
Theme highContrastBaseType = GetHighContrastBaseType();
|
||||
ChangeTheme(highContrastBaseType);
|
||||
}
|
||||
else
|
||||
{
|
||||
string baseColor = WindowsThemeHelper.GetWindowsBaseColor();
|
||||
ChangeTheme((Theme)Enum.Parse(typeof(Theme), baseColor));
|
||||
}
|
||||
}
|
||||
|
||||
private void ChangeTheme(Theme theme)
|
||||
{
|
||||
Theme oldTheme = currentTheme;
|
||||
if (theme == currentTheme)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (theme == Theme.HighContrastOne)
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastOneTheme);
|
||||
currentTheme = Theme.HighContrastOne;
|
||||
}
|
||||
else if (theme == Theme.HighContrastTwo)
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastTwoTheme);
|
||||
currentTheme = Theme.HighContrastTwo;
|
||||
}
|
||||
else if (theme == Theme.HighContrastWhite)
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastWhiteTheme);
|
||||
currentTheme = Theme.HighContrastWhite;
|
||||
}
|
||||
else if (theme == Theme.HighContrastBlack)
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastBlackTheme);
|
||||
currentTheme = Theme.HighContrastBlack;
|
||||
}
|
||||
else if (theme == Theme.Light)
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, LightTheme);
|
||||
currentTheme = Theme.Light;
|
||||
}
|
||||
else if (theme == Theme.Dark)
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, DarkTheme);
|
||||
currentTheme = Theme.Dark;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentTheme = Theme.None;
|
||||
}
|
||||
|
||||
ThemeChanged?.Invoke(oldTheme, currentTheme);
|
||||
}
|
||||
|
||||
private void Current_ThemeChanged(object sender, ThemeChangedEventArgs e)
|
||||
{
|
||||
ResetTheme();
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ThemeChanged -= Current_ThemeChanged;
|
||||
SystemParameters.StaticPropertyChanged -= SystemParameters_StaticPropertyChanged;
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void ThemeChangedHandler(Theme oldTheme, Theme newTheme);
|
||||
|
||||
public enum Theme
|
||||
{
|
||||
None,
|
||||
Light,
|
||||
Dark,
|
||||
HighContrastOne,
|
||||
HighContrastTwo,
|
||||
HighContrastBlack,
|
||||
HighContrastWhite,
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using FancyZonesEditor.Utils;
|
||||
|
||||
namespace FancyZonesEditor.ViewModels
|
||||
@ -22,14 +21,6 @@ namespace FancyZonesEditor.ViewModels
|
||||
|
||||
public static double DesktopPreviewMultiplier { get; private set; }
|
||||
|
||||
public Visibility DesktopsPanelVisibility
|
||||
{
|
||||
get
|
||||
{
|
||||
return App.Overlay.MultiMonitorMode ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
public RelayCommand AddCommand { get; set; }
|
||||
|
||||
public RelayCommand DeleteCommand { get; set; }
|
||||
@ -57,7 +48,7 @@ namespace FancyZonesEditor.ViewModels
|
||||
|
||||
double maxMultiplier = MaxPreviewDisplaySize / maxDimension;
|
||||
double minMultiplier = MinPreviewDisplaySize / minDimension;
|
||||
DesktopPreviewMultiplier = (minMultiplier + maxMultiplier) / 2;
|
||||
DesktopPreviewMultiplier = (minMultiplier + maxMultiplier) / 3.5;
|
||||
}
|
||||
|
||||
private void RaisePropertyChanged(string propertyName)
|
||||
|
@ -4,7 +4,8 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Title="Window1" Height="450" Width="800"
|
||||
Title="Window1" Height="450"
|
||||
Width="800"
|
||||
WindowState="Maximized"
|
||||
ShowInTaskbar="False"
|
||||
ResizeMode="NoResize"
|
||||
@ -16,7 +17,7 @@
|
||||
|
||||
|
||||
<Grid x:Name="Body">
|
||||
<Rectangle Fill="White" Opacity="0.5"/>
|
||||
<Rectangle Fill="White" Opacity="1"/>
|
||||
|
||||
<Grid x:Name="Window1" >
|
||||
<Border BorderThickness="2" BorderBrush="Black">
|
||||
@ -25,7 +26,7 @@
|
||||
<Thumb Background="Red" Height="36" VerticalAlignment="Top"/>
|
||||
<Button Height="36" Width="36" VerticalAlignment="Top" Background="Red" FontFamily="Segoe UI Symbol" FontSize="16" Content="✖" HorizontalAlignment="Right"/>
|
||||
-->
|
||||
<Rectangle Fill="Black" Opacity="0.2"/>
|
||||
<Rectangle Fill="Black" Opacity="1"/>
|
||||
<!--
|
||||
<Grid Width="24" Height="24" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,10,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 434 B |
Binary file not shown.
Before Width: | Height: | Size: 317 B |
Binary file not shown.
Before Width: | Height: | Size: 279 B |
@ -621,6 +621,12 @@ void FancyZones::ToggleEditor() noexcept
|
||||
return;
|
||||
}
|
||||
|
||||
wil::unique_cotaskmem_string virtualDesktopId;
|
||||
if (!SUCCEEDED(StringFromCLSID(m_currentDesktopId, &virtualDesktopId)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Divider: /
|
||||
* Parts:
|
||||
@ -639,13 +645,16 @@ void FancyZones::ToggleEditor() noexcept
|
||||
std::wstring params;
|
||||
const std::wstring divider = L"/";
|
||||
params += std::to_wstring(GetCurrentProcessId()) + divider; /* Process id */
|
||||
|
||||
const bool spanZonesAcrossMonitors = m_settings->GetSettings()->spanZonesAcrossMonitors;
|
||||
params += std::to_wstring(spanZonesAcrossMonitors) + divider; /* Span zones */
|
||||
|
||||
std::vector<std::pair<HMONITOR, MONITORINFOEX>> allMonitors;
|
||||
allMonitors = FancyZonesUtils::GetAllMonitorInfo<&MONITORINFOEX::rcWork>();
|
||||
|
||||
if (spanZonesAcrossMonitors)
|
||||
{
|
||||
params += FancyZonesUtils::GenerateUniqueIdAllMonitorsArea(virtualDesktopId.get()) + divider; /* Monitor id where the Editor should be opened */
|
||||
}
|
||||
|
||||
// device id map
|
||||
std::unordered_map<std::wstring, DWORD> displayDeviceIdxMap;
|
||||
|
||||
@ -657,25 +666,15 @@ void FancyZones::ToggleEditor() noexcept
|
||||
HMONITOR monitor = monitorData.first;
|
||||
auto monitorInfo = monitorData.second;
|
||||
|
||||
std::wstring monitorId;
|
||||
std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(monitorInfo.szDevice, displayDeviceIdxMap);
|
||||
wil::unique_cotaskmem_string virtualDesktopId;
|
||||
if (SUCCEEDED(StringFromCLSID(m_currentDesktopId, &virtualDesktopId)))
|
||||
{
|
||||
monitorId = FancyZonesUtils::GenerateUniqueId(monitor, deviceId, virtualDesktopId.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::wstring monitorId = FancyZonesUtils::GenerateUniqueId(monitor, deviceId, virtualDesktopId.get());
|
||||
|
||||
if (monitor == targetMonitor)
|
||||
if (monitor == targetMonitor && !spanZonesAcrossMonitors)
|
||||
{
|
||||
params += monitorId + divider; /* Monitor id where the Editor should be opened */
|
||||
}
|
||||
|
||||
monitorsDataStr += std::move(monitorId) + divider; /* Monitor id */
|
||||
|
||||
UINT dpiX = 0;
|
||||
UINT dpiY = 0;
|
||||
if (GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY) == S_OK)
|
||||
@ -690,13 +689,15 @@ void FancyZones::ToggleEditor() noexcept
|
||||
prevDpiY = dpiY;
|
||||
}
|
||||
|
||||
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.left) + divider;
|
||||
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.top) + divider;
|
||||
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.left) + divider; /* Top coordinate */
|
||||
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.top) + divider; /* Left coordinate */
|
||||
}
|
||||
|
||||
params += std::to_wstring(allMonitors.size()) + divider; /* Monitors count */
|
||||
params += monitorsDataStr;
|
||||
|
||||
FancyZonesDataInstance().SaveFancyZonesEditorParameters(spanZonesAcrossMonitors, virtualDesktopId.get(), targetMonitor); /* Write parameters to json file */
|
||||
|
||||
if (showDpiWarning)
|
||||
{
|
||||
// We must show the message box in a separate thread, since this code is called from a low-level
|
||||
@ -709,9 +710,6 @@ void FancyZones::ToggleEditor() noexcept
|
||||
//} }.detach();
|
||||
}
|
||||
|
||||
const auto& fancyZonesData = FancyZonesDataInstance();
|
||||
fancyZonesData.SerializeDeviceInfoToTmpFile(m_currentDesktopId);
|
||||
|
||||
SHELLEXECUTEINFO sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
|
||||
sei.lpFile = NonLocalizable::FZEditorExecutablePath;
|
||||
@ -1304,7 +1302,7 @@ bool FancyZones::IsSplashScreen(HWND window)
|
||||
void FancyZones::OnEditorExitEvent() noexcept
|
||||
{
|
||||
// Collect information about changes in zone layout after editor exited.
|
||||
FancyZonesDataInstance().ParseDataFromTmpFiles();
|
||||
FancyZonesDataInstance().LoadFancyZonesData();
|
||||
UpdateZoneSets();
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "Settings.h"
|
||||
|
||||
#include <common/utils/json.h>
|
||||
#include <fancyzones/lib/util.h>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <filesystem>
|
||||
@ -24,12 +25,9 @@ namespace NonLocalizable
|
||||
|
||||
const wchar_t FancyZonesDataFile[] = L"zones-settings.json";
|
||||
const wchar_t FancyZonesAppZoneHistoryFile[] = L"app-zone-history.json";
|
||||
const wchar_t FancyZonesEditorParametersFile[] = L"editor-parameters.json";
|
||||
const wchar_t DefaultGuid[] = L"{00000000-0000-0000-0000-000000000000}";
|
||||
const wchar_t RegistryPath[] = L"Software\\SuperFancyZones";
|
||||
|
||||
const wchar_t ActiveZoneSetsTmpFileName[] = L"FancyZonesActiveZoneSets.json";
|
||||
const wchar_t AppliedZoneSetsTmpFileName[] = L"FancyZonesAppliedZoneSets.json";
|
||||
const wchar_t DeletedCustomZoneSetsTmpFileName[] = L"FancyZonesDeletedCustomZoneSets.json";
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -151,10 +149,7 @@ FancyZonesData::FancyZonesData()
|
||||
|
||||
zonesSettingsFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesDataFile);
|
||||
appZoneHistoryFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesAppZoneHistoryFile);
|
||||
|
||||
activeZoneSetTmpFileName = GetTempDirPath() + NonLocalizable::ActiveZoneSetsTmpFileName;
|
||||
appliedZoneSetTmpFileName = GetTempDirPath() + NonLocalizable::AppliedZoneSetsTmpFileName;
|
||||
deletedCustomZoneSetsTmpFileName = GetTempDirPath() + NonLocalizable::DeletedCustomZoneSetsTmpFileName;
|
||||
editorParametersFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesEditorParametersFile);
|
||||
}
|
||||
|
||||
std::optional<FancyZonesDataTypes::DeviceInfoData> FancyZonesData::FindDeviceInfo(const std::wstring& zoneWindowId) const
|
||||
@ -479,54 +474,6 @@ void FancyZonesData::SetActiveZoneSet(const std::wstring& deviceId, const FancyZ
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZonesData::SerializeDeviceInfoToTmpFile(const GUID& currentVirtualDesktop) const
|
||||
{
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, currentVirtualDesktop, activeZoneSetTmpFileName);
|
||||
}
|
||||
|
||||
void FancyZonesData::ParseDataFromTmpFiles()
|
||||
{
|
||||
ParseDeviceInfoFromTmpFile(activeZoneSetTmpFileName);
|
||||
ParseDeletedCustomZoneSetsFromTmpFile(deletedCustomZoneSetsTmpFileName);
|
||||
ParseCustomZoneSetsFromTmpFile(appliedZoneSetTmpFileName);
|
||||
SaveFancyZonesData();
|
||||
}
|
||||
|
||||
void FancyZonesData::ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::scoped_lock lock{ dataLock };
|
||||
const auto& appliedZonesets = JSONHelpers::ParseDeviceInfoFromTmpFile(tmpFilePath);
|
||||
|
||||
if (appliedZonesets)
|
||||
{
|
||||
for (const auto& zoneset : *appliedZonesets)
|
||||
{
|
||||
deviceInfoMap[zoneset.first] = std::move(zoneset.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZonesData::ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::scoped_lock lock{ dataLock };
|
||||
const auto& customZoneSets = JSONHelpers::ParseCustomZoneSetsFromTmpFile(tmpFilePath);
|
||||
|
||||
for (const auto& zoneSet : customZoneSets)
|
||||
{
|
||||
customZoneSetsMap[zoneSet.uuid] = zoneSet.data;
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZonesData::ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::scoped_lock lock{ dataLock };
|
||||
const auto& deletedCustomZoneSets = JSONHelpers::ParseDeletedCustomZoneSetsFromTmpFile(tmpFilePath);
|
||||
for (const auto& zoneSet : deletedCustomZoneSets)
|
||||
{
|
||||
customZoneSetsMap.erase(zoneSet);
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonObject FancyZonesData::GetPersistFancyZonesJSON()
|
||||
{
|
||||
return JSONHelpers::GetPersistFancyZonesJSON(zonesSettingsFileName, appZoneHistoryFileName);
|
||||
@ -569,6 +516,69 @@ void FancyZonesData::SaveAppZoneHistory() const
|
||||
JSONHelpers::SaveAppZoneHistory(appZoneHistoryFileName, appZoneHistoryMap);
|
||||
}
|
||||
|
||||
void FancyZonesData::SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors, const std::wstring& virtualDesktopId, const HMONITOR& targetMonitor) const
|
||||
{
|
||||
JSONHelpers::EditorArgs argsJson; /* json arguments */
|
||||
argsJson.processId = GetCurrentProcessId(); /* Process id */
|
||||
argsJson.spanZonesAcrossMonitors = spanZonesAcrossMonitors; /* Span zones */
|
||||
|
||||
if (spanZonesAcrossMonitors)
|
||||
{
|
||||
auto monitorRect = FancyZonesUtils::GetAllMonitorsCombinedRect<&MONITORINFOEX::rcWork>();
|
||||
std::wstring monitorId = FancyZonesUtils::GenerateUniqueIdAllMonitorsArea(virtualDesktopId);
|
||||
|
||||
JSONHelpers::MonitorInfo monitorJson;
|
||||
monitorJson.id = monitorId;
|
||||
monitorJson.top = monitorRect.top;
|
||||
monitorJson.left = monitorRect.left;
|
||||
monitorJson.isSelected = true;
|
||||
monitorJson.dpi = 0; // unused
|
||||
|
||||
argsJson.monitors.emplace_back(std::move(monitorJson)); /* add monitor data */
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::pair<HMONITOR, MONITORINFOEX>> allMonitors;
|
||||
allMonitors = FancyZonesUtils::GetAllMonitorInfo<&MONITORINFOEX::rcWork>();
|
||||
|
||||
// device id map for correct device ids
|
||||
std::unordered_map<std::wstring, DWORD> displayDeviceIdxMap;
|
||||
|
||||
for (auto& monitorData : allMonitors)
|
||||
{
|
||||
HMONITOR monitor = monitorData.first;
|
||||
auto monitorInfo = monitorData.second;
|
||||
|
||||
JSONHelpers::MonitorInfo monitorJson;
|
||||
|
||||
std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(monitorInfo.szDevice, displayDeviceIdxMap);
|
||||
std::wstring monitorId = FancyZonesUtils::GenerateUniqueId(monitor, deviceId, virtualDesktopId);
|
||||
|
||||
if (monitor == targetMonitor)
|
||||
{
|
||||
monitorJson.isSelected = true; /* Is monitor selected for the main editor window opening */
|
||||
}
|
||||
|
||||
monitorJson.id = monitorId; /* Monitor id */
|
||||
|
||||
UINT dpiX = 0;
|
||||
UINT dpiY = 0;
|
||||
if (GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY) == S_OK)
|
||||
{
|
||||
monitorJson.dpi = dpiX; /* DPI */
|
||||
}
|
||||
|
||||
monitorJson.top = monitorInfo.rcMonitor.top; /* Top coordinate */
|
||||
monitorJson.left = monitorInfo.rcMonitor.left; /* Left coordinate */
|
||||
|
||||
argsJson.monitors.emplace_back(std::move(monitorJson)); /* add monitor data */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
json::to_file(editorParametersFileName, JSONHelpers::EditorArgs::ToJson(argsJson));
|
||||
}
|
||||
|
||||
void FancyZonesData::RemoveDesktopAppZoneHistory(const std::wstring& desktopId)
|
||||
{
|
||||
for (auto it = std::begin(appZoneHistoryMap); it != std::end(appZoneHistoryMap);)
|
||||
|
@ -78,9 +78,6 @@ public:
|
||||
|
||||
void SetActiveZoneSet(const std::wstring& deviceId, const FancyZonesDataTypes::ZoneSetData& zoneSet);
|
||||
|
||||
void SerializeDeviceInfoToTmpFile(const GUID& currentVirtualDesktop) const;
|
||||
void ParseDataFromTmpFiles();
|
||||
|
||||
json::JsonObject GetPersistFancyZonesJSON();
|
||||
|
||||
void LoadFancyZonesData();
|
||||
@ -88,6 +85,8 @@ public:
|
||||
void SaveZoneSettings() const;
|
||||
void SaveAppZoneHistory() const;
|
||||
|
||||
void SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors, const std::wstring& virtualDesktopId, const HMONITOR& targetMonitor) const;
|
||||
|
||||
private:
|
||||
#if defined(UNIT_TESTS)
|
||||
friend class FancyZonesUnitTests::FancyZonesDataUnitTests;
|
||||
@ -101,6 +100,11 @@ private:
|
||||
deviceInfoMap[deviceId] = data;
|
||||
}
|
||||
|
||||
inline void SetCustomZonesets(const std::wstring& uuid, FancyZonesDataTypes::CustomZoneSetData data)
|
||||
{
|
||||
customZoneSetsMap[uuid] = data;
|
||||
}
|
||||
|
||||
inline bool ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON)
|
||||
{
|
||||
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||
@ -121,10 +125,6 @@ private:
|
||||
appZoneHistoryFileName = result + L"\\" + std::wstring(L"app-zone-history.json");
|
||||
}
|
||||
#endif
|
||||
void ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath);
|
||||
void ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath);
|
||||
void ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath);
|
||||
|
||||
void RemoveDesktopAppZoneHistory(const std::wstring& desktopId);
|
||||
|
||||
// Maps app path to app's zone history data
|
||||
@ -136,10 +136,7 @@ private:
|
||||
|
||||
std::wstring zonesSettingsFileName;
|
||||
std::wstring appZoneHistoryFileName;
|
||||
|
||||
std::wstring activeZoneSetTmpFileName;
|
||||
std::wstring appliedZoneSetTmpFileName;
|
||||
std::wstring deletedCustomZoneSetsTmpFileName;
|
||||
std::wstring editorParametersFileName;
|
||||
|
||||
mutable std::recursive_mutex dataLock;
|
||||
};
|
||||
|
@ -45,6 +45,7 @@ namespace FancyZonesDataTypes
|
||||
int height;
|
||||
};
|
||||
std::vector<CanvasLayoutInfo::Rect> zones;
|
||||
int sensitivityRadius;
|
||||
};
|
||||
|
||||
struct GridLayoutInfo
|
||||
@ -62,6 +63,9 @@ namespace FancyZonesDataTypes
|
||||
const std::vector<int>& rowsPercents;
|
||||
const std::vector<int>& columnsPercents;
|
||||
const std::vector<std::vector<int>>& cellChildMap;
|
||||
bool showSpacing;
|
||||
int spacing;
|
||||
int sensitivityRadius;
|
||||
};
|
||||
|
||||
GridLayoutInfo(const Minimal& info);
|
||||
@ -74,16 +78,22 @@ namespace FancyZonesDataTypes
|
||||
|
||||
inline int rows() const { return m_rows; }
|
||||
inline int columns() const { return m_columns; }
|
||||
|
||||
inline const std::vector<int>& rowsPercents() const { return m_rowsPercents; };
|
||||
inline const std::vector<int>& columnsPercents() const { return m_columnsPercents; };
|
||||
inline const std::vector<std::vector<int>>& cellChildMap() const { return m_cellChildMap; };
|
||||
|
||||
inline bool showSpacing() const { return m_showSpacing; }
|
||||
inline int spacing() const { return m_spacing; }
|
||||
inline int sensitivityRadius() const { return m_sensitivityRadius; }
|
||||
|
||||
int m_rows;
|
||||
int m_columns;
|
||||
std::vector<int> m_rowsPercents;
|
||||
std::vector<int> m_columnsPercents;
|
||||
std::vector<std::vector<int>> m_cellChildMap;
|
||||
bool m_showSpacing;
|
||||
int m_spacing;
|
||||
int m_sensitivityRadius;
|
||||
};
|
||||
|
||||
struct CustomZoneSetData
|
||||
|
@ -17,16 +17,13 @@
|
||||
namespace NonLocalizable
|
||||
{
|
||||
const wchar_t ActiveZoneSetStr[] = L"active-zoneset";
|
||||
const wchar_t AppliedZonesets[] = L"applied-zonesets";
|
||||
const wchar_t AppPathStr[] = L"app-path";
|
||||
const wchar_t AppZoneHistoryStr[] = L"app-zone-history";
|
||||
const wchar_t CanvasStr[] = L"canvas";
|
||||
const wchar_t CellChildMapStr[] = L"cell-child-map";
|
||||
const wchar_t ColumnsPercentageStr[] = L"columns-percentage";
|
||||
const wchar_t ColumnsStr[] = L"columns";
|
||||
const wchar_t CreatedCustomZoneSets[] = L"created-custom-zone-sets";
|
||||
const wchar_t CustomZoneSetsStr[] = L"custom-zone-sets";
|
||||
const wchar_t DeletedCustomZoneSetsStr[] = L"deleted-custom-zone-sets";
|
||||
const wchar_t DeviceIdStr[] = L"device-id";
|
||||
const wchar_t DevicesStr[] = L"devices";
|
||||
const wchar_t EditorShowSpacingStr[] = L"editor-show-spacing";
|
||||
@ -42,6 +39,10 @@ namespace NonLocalizable
|
||||
const wchar_t RefWidthStr[] = L"ref-width";
|
||||
const wchar_t RowsPercentageStr[] = L"rows-percentage";
|
||||
const wchar_t RowsStr[] = L"rows";
|
||||
const wchar_t SensitivityRadius[] = L"sensitivity-radius";
|
||||
const wchar_t ShowSpacing[] = L"show-spacing";
|
||||
const wchar_t Spacing[] = L"spacing";
|
||||
const wchar_t Templates[] = L"templates";
|
||||
const wchar_t TypeStr[] = L"type";
|
||||
const wchar_t UuidStr[] = L"uuid";
|
||||
const wchar_t WidthStr[] = L"width";
|
||||
@ -51,6 +52,16 @@ namespace NonLocalizable
|
||||
const wchar_t ZoneIndexStr[] = L"zone-index";
|
||||
const wchar_t ZoneSetUuidStr[] = L"zoneset-uuid";
|
||||
const wchar_t ZonesStr[] = L"zones";
|
||||
|
||||
// Editor arguments
|
||||
const wchar_t Dpi[] = L"dpi";
|
||||
const wchar_t MonitorId[] = L"monitor-id";
|
||||
const wchar_t TopCoordinate[] = L"top-coordinate";
|
||||
const wchar_t LeftCoordinate[] = L"left-coordinate";
|
||||
const wchar_t IsSelected[] = L"is-selected";
|
||||
const wchar_t ProcessId[] = L"process-id";
|
||||
const wchar_t SpanZonesAcrossMonitors[] = L"span-zones-across-monitors";
|
||||
const wchar_t Monitors[] = L"monitors";
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -130,6 +141,7 @@ namespace JSONHelpers
|
||||
zonesJson.Append(zoneJson);
|
||||
}
|
||||
infoJson.SetNamedValue(NonLocalizable::ZonesStr, zonesJson);
|
||||
infoJson.SetNamedValue(NonLocalizable::SensitivityRadius, json::value(canvasInfo.sensitivityRadius));
|
||||
return infoJson;
|
||||
}
|
||||
|
||||
@ -154,6 +166,8 @@ namespace JSONHelpers
|
||||
FancyZonesDataTypes::CanvasLayoutInfo::Rect zone{ x, y, width, height };
|
||||
info.zones.push_back(zone);
|
||||
}
|
||||
|
||||
info.sensitivityRadius = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::SensitivityRadius, DefaultValues::SensitivityRadius));
|
||||
return info;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
@ -176,6 +190,10 @@ namespace JSONHelpers
|
||||
cellChildMapJson.Append(NumVecToJsonArray(gridInfo.m_cellChildMap[i]));
|
||||
}
|
||||
infoJson.SetNamedValue(NonLocalizable::CellChildMapStr, cellChildMapJson);
|
||||
|
||||
infoJson.SetNamedValue(NonLocalizable::SensitivityRadius, json::value(gridInfo.m_sensitivityRadius));
|
||||
infoJson.SetNamedValue(NonLocalizable::ShowSpacing, json::value(gridInfo.m_showSpacing));
|
||||
infoJson.SetNamedValue(NonLocalizable::Spacing, json::value(gridInfo.m_spacing));
|
||||
|
||||
return infoJson;
|
||||
}
|
||||
@ -210,6 +228,10 @@ namespace JSONHelpers
|
||||
info.cellChildMap().push_back(JsonArrayToNumVec(cellsArray));
|
||||
}
|
||||
|
||||
info.m_showSpacing = infoJson.GetNamedBoolean(NonLocalizable::ShowSpacing, DefaultValues::ShowSpacing);
|
||||
info.m_spacing = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::Spacing, DefaultValues::Spacing));
|
||||
info.m_sensitivityRadius = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::SensitivityRadius, DefaultValues::SensitivityRadius));
|
||||
|
||||
return info;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
@ -449,64 +471,37 @@ namespace JSONHelpers
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonObject AppliedZonesetsJSON::ToJson(const TDeviceInfoMap& deviceInfoMap)
|
||||
json::JsonObject MonitorInfo::ToJson(const MonitorInfo& monitor)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
|
||||
json::JsonArray array;
|
||||
for (const auto& info : deviceInfoMap)
|
||||
{
|
||||
JSONHelpers::DeviceInfoJSON deviceInfoJson{ info.first, info.second };
|
||||
array.Append(JSONHelpers::DeviceInfoJSON::ToJson(deviceInfoJson));
|
||||
}
|
||||
result.SetNamedValue(NonLocalizable::Dpi, json::value(monitor.dpi));
|
||||
result.SetNamedValue(NonLocalizable::MonitorId, json::value(monitor.id));
|
||||
result.SetNamedValue(NonLocalizable::TopCoordinate, json::value(monitor.top));
|
||||
result.SetNamedValue(NonLocalizable::LeftCoordinate, json::value(monitor.left));
|
||||
result.SetNamedValue(NonLocalizable::IsSelected, json::value(monitor.isSelected));
|
||||
|
||||
result.SetNamedValue(NonLocalizable::AppliedZonesets, array);
|
||||
return result;
|
||||
}
|
||||
|
||||
json::JsonObject AppliedZonesetsJSON::ToJson(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop)
|
||||
json::JsonObject EditorArgs::ToJson(const EditorArgs& args)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
|
||||
json::JsonArray array;
|
||||
for (const auto& info : deviceInfoMap)
|
||||
result.SetNamedValue(NonLocalizable::ProcessId, json::value(args.processId));
|
||||
result.SetNamedValue(NonLocalizable::SpanZonesAcrossMonitors, json::value(args.spanZonesAcrossMonitors));
|
||||
|
||||
json::JsonArray monitors;
|
||||
for (const auto& monitor : args.monitors)
|
||||
{
|
||||
std::optional<FancyZonesDataTypes::DeviceIdData> id = FancyZonesUtils::ParseDeviceId(info.first);
|
||||
if (id.has_value() && id->virtualDesktopId == currentVirtualDesktop)
|
||||
{
|
||||
JSONHelpers::DeviceInfoJSON deviceInfoJson{ info.first, info.second };
|
||||
array.Append(JSONHelpers::DeviceInfoJSON::ToJson(deviceInfoJson));
|
||||
}
|
||||
monitors.Append(MonitorInfo::ToJson(monitor));
|
||||
}
|
||||
|
||||
result.SetNamedValue(NonLocalizable::AppliedZonesets, array);
|
||||
result.SetNamedValue(NonLocalizable::Monitors, monitors);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<TDeviceInfoMap> AppliedZonesetsJSON::FromJson(const json::JsonObject& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
TDeviceInfoMap appliedZonesets;
|
||||
|
||||
auto zonesets = json.GetNamedArray(NonLocalizable::AppliedZonesets);
|
||||
for (const auto& zoneset : zonesets)
|
||||
{
|
||||
std::optional<DeviceInfoJSON> device = DeviceInfoJSON::FromJson(zoneset.GetObjectW());
|
||||
if (device.has_value())
|
||||
{
|
||||
appliedZonesets.insert(std::make_pair(device->deviceId, device->data));
|
||||
}
|
||||
}
|
||||
|
||||
return appliedZonesets;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName)
|
||||
{
|
||||
auto result = json::from_file(zonesSettingsFileName);
|
||||
@ -534,12 +529,27 @@ namespace JSONHelpers
|
||||
|
||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap)
|
||||
{
|
||||
json::JsonObject root{};
|
||||
auto before = json::from_file(zonesSettingsFileName);
|
||||
|
||||
json::JsonObject root{};
|
||||
json::JsonArray templates{};
|
||||
|
||||
try
|
||||
{
|
||||
if (before.has_value() && before->HasKey(NonLocalizable::Templates))
|
||||
{
|
||||
templates = before->GetNamedArray(NonLocalizable::Templates);
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
root.SetNamedValue(NonLocalizable::DevicesStr, JSONHelpers::SerializeDeviceInfos(deviceInfoMap));
|
||||
root.SetNamedValue(NonLocalizable::CustomZoneSetsStr, JSONHelpers::SerializeCustomZoneSets(customZoneSetsMap));
|
||||
|
||||
auto before = json::from_file(zonesSettingsFileName);
|
||||
root.SetNamedValue(NonLocalizable::Templates, templates);
|
||||
|
||||
if (!before.has_value() || before.value().Stringify() != root.Stringify())
|
||||
{
|
||||
Trace::FancyZones::DataChanged();
|
||||
@ -665,104 +675,4 @@ namespace JSONHelpers
|
||||
|
||||
return customZoneSetsJSON;
|
||||
}
|
||||
|
||||
void SerializeDeviceInfoToTmpFile(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop, std::wstring_view tmpFilePath)
|
||||
{
|
||||
json::to_file(tmpFilePath, JSONHelpers::AppliedZonesetsJSON::ToJson(deviceInfoMap, currentVirtualDesktop));
|
||||
}
|
||||
|
||||
void SerializeCustomZoneSetsToTmpFile(const TCustomZoneSetsMap& customZoneSetsMap, std::wstring_view tmpFilePath)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
|
||||
json::JsonArray array;
|
||||
for (const auto& zoneSet : customZoneSetsMap)
|
||||
{
|
||||
CustomZoneSetJSON json{ zoneSet.first, zoneSet.second };
|
||||
array.Append(JSONHelpers::CustomZoneSetJSON::ToJson(json));
|
||||
}
|
||||
|
||||
result.SetNamedValue(NonLocalizable::CreatedCustomZoneSets, array);
|
||||
json::to_file(tmpFilePath, result);
|
||||
}
|
||||
|
||||
std::optional<TDeviceInfoMap> ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::optional<TDeviceInfoMap> result{ std::nullopt };
|
||||
if (std::filesystem::exists(tmpFilePath))
|
||||
{
|
||||
if (auto zoneSetJson = json::from_file(tmpFilePath); zoneSetJson.has_value())
|
||||
{
|
||||
if (auto deviceInfo = JSONHelpers::AppliedZonesetsJSON::FromJson(zoneSetJson.value()); deviceInfo.has_value())
|
||||
{
|
||||
result = std::move(deviceInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::trace(L"ParseDeviceInfoFromTmpFile: AppliedZonesetsJSON::FromJson parsing error, {}", zoneSetJson.value().Stringify());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeleteTmpFile(tmpFilePath);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<CustomZoneSetJSON> ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::vector<CustomZoneSetJSON> result;
|
||||
if (std::filesystem::exists(tmpFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (auto customZoneSetJson = json::from_file(tmpFilePath); customZoneSetJson.has_value())
|
||||
{
|
||||
auto zoneSetArray = customZoneSetJson.value().GetNamedArray(NonLocalizable::CreatedCustomZoneSets);
|
||||
for (const auto& zoneSet : zoneSetArray)
|
||||
{
|
||||
if (auto customZoneSet = JSONHelpers::CustomZoneSetJSON::FromJson(zoneSet.GetObjectW()); customZoneSet.has_value())
|
||||
{
|
||||
result.emplace_back(std::move(*customZoneSet));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::trace(L"ParseCustomZoneSetsFromTmpFile: CustomZoneSetJSON::FromJson parsing error, {}", zoneSet.GetObjectW().Stringify());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& err)
|
||||
{
|
||||
Logger::trace(L"ParseCustomZoneSetsFromTmpFile: CustomZoneSetJSON::FromJson parsing error, {}", err.message());
|
||||
}
|
||||
|
||||
DeleteTmpFile(tmpFilePath);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::vector<std::wstring> result{};
|
||||
if (std::filesystem::exists(tmpFilePath))
|
||||
{
|
||||
auto deletedZoneSetsJson = json::from_file(tmpFilePath);
|
||||
try
|
||||
{
|
||||
auto deletedCustomZoneSets = deletedZoneSetsJson->GetNamedArray(NonLocalizable::DeletedCustomZoneSetsStr);
|
||||
for (auto zoneSet : deletedCustomZoneSets)
|
||||
{
|
||||
std::wstring uuid = L"{" + std::wstring{ zoneSet.GetString() } + L"}";
|
||||
result.push_back(uuid);
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
}
|
||||
|
||||
DeleteTmpFile(tmpFilePath);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -59,11 +59,24 @@ namespace JSONHelpers
|
||||
using TDeviceInfoMap = std::unordered_map<std::wstring, FancyZonesDataTypes::DeviceInfoData>;
|
||||
using TCustomZoneSetsMap = std::unordered_map<std::wstring, FancyZonesDataTypes::CustomZoneSetData>;
|
||||
|
||||
struct AppliedZonesetsJSON
|
||||
struct MonitorInfo
|
||||
{
|
||||
static json::JsonObject ToJson(const TDeviceInfoMap& deviceInfoMap);
|
||||
static json::JsonObject ToJson(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop);
|
||||
static std::optional<TDeviceInfoMap> FromJson(const json::JsonObject& json);
|
||||
int dpi;
|
||||
std::wstring id;
|
||||
int top;
|
||||
int left;
|
||||
bool isSelected = false;
|
||||
|
||||
static json::JsonObject ToJson(const MonitorInfo& monitor);
|
||||
};
|
||||
|
||||
struct EditorArgs
|
||||
{
|
||||
DWORD processId;
|
||||
bool spanZonesAcrossMonitors;
|
||||
std::vector<MonitorInfo> monitors;
|
||||
|
||||
static json::JsonObject ToJson(const EditorArgs& args);
|
||||
};
|
||||
|
||||
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName);
|
||||
@ -79,14 +92,4 @@ namespace JSONHelpers
|
||||
|
||||
TCustomZoneSetsMap ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON);
|
||||
json::JsonArray SerializeCustomZoneSets(const TCustomZoneSetsMap& customZoneSetsMap);
|
||||
|
||||
void SerializeDeviceInfoToTmpFile(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop, std::wstring_view tmpFilePath);
|
||||
std::optional<TDeviceInfoMap> ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath);
|
||||
std::vector<CustomZoneSetJSON> ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath);
|
||||
std::vector<std::wstring> ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath);
|
||||
|
||||
#if defined(UNIT_TESTS)
|
||||
void SerializeCustomZoneSetsToTmpFile(const TCustomZoneSetsMap& customZoneSetsMap, std::wstring_view tmpFilePath);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -189,7 +189,8 @@ namespace FancyZonesUnitTests
|
||||
|
||||
TEST_CLASS (CanvasLayoutInfoUnitTests)
|
||||
{
|
||||
json::JsonObject m_json = json::JsonObject::Parse(L"{\"ref-width\": 123, \"ref-height\": 321, \"zones\": [{\"X\": 11, \"Y\": 22, \"width\": 33, \"height\": 44}, {\"X\": 55, \"Y\": 66, \"width\": 77, \"height\": 88}]}");
|
||||
json::JsonObject m_json = json::JsonObject::Parse(L"{\"ref-width\": 123, \"ref-height\": 321, \"zones\": [{\"X\": 11, \"Y\": 22, \"width\": 33, \"height\": 44}, {\"X\": 55, \"Y\": 66, \"width\": 77, \"height\": 88}], \"sensitivity-radius\": 50}");
|
||||
json::JsonObject m_jsonWithoutOptionalValues = json::JsonObject::Parse(L"{\"ref-width\": 123, \"ref-height\": 321, \"zones\": [{\"X\": 11, \"Y\": 22, \"width\": 33, \"height\": 44}, {\"X\": 55, \"Y\": 66, \"width\": 77, \"height\": 88}]}");
|
||||
|
||||
TEST_METHOD (ToJson)
|
||||
{
|
||||
@ -197,6 +198,7 @@ namespace FancyZonesUnitTests
|
||||
info.lastWorkAreaWidth = 123;
|
||||
info.lastWorkAreaHeight = 321;
|
||||
info.zones = { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } };
|
||||
info.sensitivityRadius = 50;
|
||||
|
||||
auto actual = CanvasLayoutInfoJSON::ToJson(info);
|
||||
compareJsonObjects(m_json, actual);
|
||||
@ -208,6 +210,7 @@ namespace FancyZonesUnitTests
|
||||
expected.lastWorkAreaWidth = 123;
|
||||
expected.lastWorkAreaHeight = 321;
|
||||
expected.zones = { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } };
|
||||
expected.sensitivityRadius = 50;
|
||||
|
||||
auto actual = CanvasLayoutInfoJSON::FromJson(m_json);
|
||||
Assert::IsTrue(actual.has_value());
|
||||
@ -215,6 +218,30 @@ namespace FancyZonesUnitTests
|
||||
Assert::AreEqual(expected.lastWorkAreaHeight, actual->lastWorkAreaHeight);
|
||||
Assert::AreEqual(expected.lastWorkAreaWidth, actual->lastWorkAreaWidth);
|
||||
Assert::AreEqual(expected.zones.size(), actual->zones.size());
|
||||
Assert::AreEqual(expected.sensitivityRadius, actual->sensitivityRadius);
|
||||
for (int i = 0; i < expected.zones.size(); i++)
|
||||
{
|
||||
Assert::AreEqual(expected.zones[i].x, actual->zones[i].x);
|
||||
Assert::AreEqual(expected.zones[i].y, actual->zones[i].y);
|
||||
Assert::AreEqual(expected.zones[i].width, actual->zones[i].width);
|
||||
Assert::AreEqual(expected.zones[i].height, actual->zones[i].height);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD (FromJsonWithoutOptionalValues)
|
||||
{
|
||||
CanvasLayoutInfo expected;
|
||||
expected.lastWorkAreaWidth = 123;
|
||||
expected.lastWorkAreaHeight = 321;
|
||||
expected.zones = { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } };
|
||||
|
||||
auto actual = CanvasLayoutInfoJSON::FromJson(m_jsonWithoutOptionalValues);
|
||||
Assert::IsTrue(actual.has_value());
|
||||
|
||||
Assert::AreEqual(expected.lastWorkAreaHeight, actual->lastWorkAreaHeight);
|
||||
Assert::AreEqual(expected.lastWorkAreaWidth, actual->lastWorkAreaWidth);
|
||||
Assert::AreEqual(expected.zones.size(), actual->zones.size());
|
||||
Assert::AreEqual(DefaultValues::SensitivityRadius, actual->sensitivityRadius);
|
||||
for (int i = 0; i < expected.zones.size(); i++)
|
||||
{
|
||||
Assert::AreEqual(expected.zones[i].x, actual->zones[i].x);
|
||||
@ -226,7 +253,7 @@ namespace FancyZonesUnitTests
|
||||
|
||||
TEST_METHOD (FromJsonMissingKeys)
|
||||
{
|
||||
CanvasLayoutInfo info{ 123, 321, { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } } };
|
||||
CanvasLayoutInfo info{ 123, 321, { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } }, 50 };
|
||||
const auto json = CanvasLayoutInfoJSON::ToJson(info);
|
||||
|
||||
auto iter = json.First();
|
||||
@ -234,6 +261,11 @@ namespace FancyZonesUnitTests
|
||||
{
|
||||
json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify());
|
||||
modifiedJson.Remove(iter.Current().Key());
|
||||
if (iter.Current().Key() == L"sensitivity-radius")
|
||||
{
|
||||
iter.MoveNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
auto actual = CanvasLayoutInfoJSON::FromJson(modifiedJson);
|
||||
Assert::IsFalse(actual.has_value());
|
||||
@ -436,6 +468,27 @@ namespace FancyZonesUnitTests
|
||||
compareJsonObjects(expected, actual);
|
||||
}
|
||||
|
||||
|
||||
TEST_METHOD (ToJsonWithOptionals)
|
||||
{
|
||||
json::JsonObject expected = json::JsonObject();
|
||||
expected = json::JsonObject::Parse(L"{\"rows\": 3, \"columns\": 4}");
|
||||
expected.SetNamedValue(L"rows-percentage", m_rowsArray);
|
||||
expected.SetNamedValue(L"columns-percentage", m_columnsArray);
|
||||
expected.SetNamedValue(L"cell-child-map", m_cells);
|
||||
expected.SetNamedValue(L"show-spacing", json::value(true));
|
||||
expected.SetNamedValue(L"spacing", json::value(99));
|
||||
expected.SetNamedValue(L"sensitivity-radius", json::value(55));
|
||||
|
||||
GridLayoutInfo info = m_info;
|
||||
info.m_sensitivityRadius = 55;
|
||||
info.m_showSpacing = true;
|
||||
info.m_spacing = 99;
|
||||
|
||||
auto actual = GridLayoutInfoJSON::ToJson(info);
|
||||
compareJsonObjects(expected, actual);
|
||||
}
|
||||
|
||||
TEST_METHOD (FromJson)
|
||||
{
|
||||
json::JsonObject json = json::JsonObject(m_gridJson);
|
||||
@ -514,6 +567,27 @@ namespace FancyZonesUnitTests
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(FromJsonWithOptionals)
|
||||
{
|
||||
json::JsonObject json = json::JsonObject();
|
||||
json = json::JsonObject::Parse(L"{\"rows\": 3, \"columns\": 4}");
|
||||
json.SetNamedValue(L"rows-percentage", m_rowsArray);
|
||||
json.SetNamedValue(L"columns-percentage", m_columnsArray);
|
||||
json.SetNamedValue(L"cell-child-map", m_cells);
|
||||
json.SetNamedValue(L"show-spacing", json::value(true));
|
||||
json.SetNamedValue(L"spacing", json::value(99));
|
||||
json.SetNamedValue(L"sensitivity-radius", json::value(55));
|
||||
|
||||
GridLayoutInfo expected = m_info;
|
||||
expected.m_sensitivityRadius = 55;
|
||||
expected.m_showSpacing = true;
|
||||
expected.m_spacing = 99;
|
||||
|
||||
auto actual = GridLayoutInfoJSON::FromJson(json);
|
||||
Assert::IsTrue(actual.has_value());
|
||||
compareGridInfos(expected, *actual);
|
||||
}
|
||||
|
||||
TEST_METHOD (FromJsonInvalidTypes)
|
||||
{
|
||||
json::JsonObject gridJson = json::JsonObject::Parse(L"{\"rows\": \"три\", \"columns\": \"четыре\"}");
|
||||
@ -938,92 +1012,6 @@ namespace FancyZonesUnitTests
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CLASS(AppliedZonesetsUnitTests)
|
||||
{
|
||||
TEST_METHOD(SingleDevice)
|
||||
{
|
||||
const std::wstring deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}";
|
||||
const std::wstring zoneUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}";
|
||||
const ZoneSetLayoutType type = ZoneSetLayoutType::Custom;
|
||||
DeviceInfoData data{ ZoneSetData{ zoneUuid, type }, true, 10, 4 };
|
||||
|
||||
TDeviceInfoMap expected;
|
||||
expected.insert(std::make_pair(deviceId, data));
|
||||
|
||||
json::JsonObject json = AppliedZonesetsJSON::ToJson(expected);
|
||||
auto actual = AppliedZonesetsJSON::FromJson(json);
|
||||
|
||||
Assert::IsTrue(actual.has_value());
|
||||
Assert::AreEqual(expected.size(), actual->size());
|
||||
for (const auto& exp : expected)
|
||||
{
|
||||
Assert::IsTrue(actual->contains(exp.first));
|
||||
|
||||
const auto act = actual->find(exp.first);
|
||||
Assert::AreEqual(exp.second.zoneCount, act->second.zoneCount);
|
||||
Assert::AreEqual(exp.second.showSpacing, act->second.showSpacing);
|
||||
Assert::AreEqual(exp.second.spacing, act->second.spacing);
|
||||
Assert::AreEqual(exp.second.activeZoneSet.uuid, act->second.activeZoneSet.uuid);
|
||||
Assert::AreEqual((int)exp.second.activeZoneSet.type, (int)act->second.activeZoneSet.type);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD (MultipleDevices)
|
||||
{
|
||||
TDeviceInfoMap expected;
|
||||
expected.insert(std::make_pair(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}", DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Columns }, true, 10, 4 }));
|
||||
expected.insert(std::make_pair(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1538}", DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502905}", ZoneSetLayoutType::Rows }, false, 8, 5 }));
|
||||
expected.insert(std::make_pair(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1537}", DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502904}", ZoneSetLayoutType::Grid }, true, 9, 6 }));
|
||||
|
||||
json::JsonObject json = AppliedZonesetsJSON::ToJson(expected);
|
||||
auto actual = AppliedZonesetsJSON::FromJson(json);
|
||||
|
||||
Assert::IsTrue(actual.has_value());
|
||||
Assert::AreEqual(expected.size(), actual->size());
|
||||
for (const auto& exp : expected)
|
||||
{
|
||||
Assert::IsTrue(actual->contains(exp.first));
|
||||
|
||||
const auto act = actual->find(exp.first);
|
||||
Assert::AreEqual(exp.second.zoneCount, act->second.zoneCount);
|
||||
Assert::AreEqual(exp.second.showSpacing, act->second.showSpacing);
|
||||
Assert::AreEqual(exp.second.spacing, act->second.spacing);
|
||||
Assert::AreEqual(exp.second.activeZoneSet.uuid, act->second.activeZoneSet.uuid);
|
||||
Assert::AreEqual((int)exp.second.activeZoneSet.type, (int)act->second.activeZoneSet.type);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD (FromJsonNoDeviceId)
|
||||
{
|
||||
json::JsonObject json = json::JsonObject::Parse(L"{\"applied-zonesets\": [{\"device-id\": \"\",\"active-zoneset\": {\"uuid\": \"{81B9FCD3-88CA-4B21-A681-5D1129A1527F}\",\"type\": \"grid\"},\"editor-show-spacing\": true,\"editor-spacing\": 5,\"editor-zone-count\": 4},{\"device-id\": \"\",\"active-zoneset\": {\"uuid\": \"{8110E0D5-4815-4A35-A5AC-DF82A65FF58B}\",\"type\": \"priority-grid\"},\"editor-show-spacing\": false,\"editor-spacing\": 6,\"editor-zone-count\": 2}]}");
|
||||
auto actual = AppliedZonesetsJSON::FromJson(json);
|
||||
Assert::IsTrue(actual.has_value());
|
||||
Assert::IsTrue(actual->empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (FromInvalidJsonNotArray)
|
||||
{
|
||||
json::JsonObject json = json::JsonObject::Parse(L"{\"applied-zonesets\": {\"device-id\": \"\",\"active-zoneset\": {\"uuid\": \"{81B9FCD3-88CA-4B21-A681-5D1129A1527F}\",\"type\": \"grid\"},\"editor-show-spacing\": true,\"editor-spacing\": 5,\"editor-zone-count\": 4}}");
|
||||
auto actual = AppliedZonesetsJSON::FromJson(json);
|
||||
Assert::IsFalse(actual.has_value());
|
||||
}
|
||||
|
||||
TEST_METHOD (FromEmptyJson)
|
||||
{
|
||||
json::JsonObject json = json::JsonObject::Parse(L"{}");
|
||||
auto actual = AppliedZonesetsJSON::FromJson(json);
|
||||
Assert::IsFalse(actual.has_value());
|
||||
}
|
||||
|
||||
TEST_METHOD (FromEmptyDeviceArray)
|
||||
{
|
||||
json::JsonObject json = json::JsonObject::Parse(L"{\"applied-zonesets\": []}");
|
||||
auto actual = AppliedZonesetsJSON::FromJson(json);
|
||||
Assert::IsTrue(actual.has_value());
|
||||
Assert::IsTrue(actual->empty());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CLASS (FancyZonesDataUnitTests)
|
||||
{
|
||||
private:
|
||||
@ -1186,74 +1174,6 @@ namespace FancyZonesUnitTests
|
||||
compareJsonArrays(expectedDevices, actual);
|
||||
}
|
||||
|
||||
TEST_METHOD (DeviceInfoSaveTemp)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
|
||||
TDeviceInfoMap deviceInfoMap;
|
||||
DeviceInfoData deviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 };
|
||||
deviceInfoMap.insert(std::make_pair(m_defaultDeviceId, deviceInfoData));
|
||||
|
||||
const std::wstring path = data.zonesSettingsFileName + L".test_tmp";
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_defaultVDId, path);
|
||||
|
||||
bool actualFileExists = std::filesystem::exists(path);
|
||||
Assert::IsTrue(actualFileExists);
|
||||
|
||||
auto expectedData = AppliedZonesetsJSON::ToJson(deviceInfoMap);
|
||||
auto actualSavedData = json::from_file(path);
|
||||
std::filesystem::remove(path); //clean up before compare asserts
|
||||
|
||||
Assert::IsTrue(actualSavedData.has_value());
|
||||
compareJsonObjects(expectedData, *actualSavedData);
|
||||
}
|
||||
|
||||
TEST_METHOD (DeviceInfoReadTemp)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
|
||||
const std::wstring deviceId = m_defaultDeviceId;
|
||||
DeviceInfoData expected{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 };
|
||||
|
||||
TDeviceInfoMap expectedDeviceInfoMap;
|
||||
expectedDeviceInfoMap.insert(std::make_pair(deviceId, expected));
|
||||
|
||||
const std::wstring path = data.zonesSettingsFileName + L".test_tmp";
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(expectedDeviceInfoMap, m_defaultVDId, path);
|
||||
|
||||
data.ParseDeviceInfoFromTmpFile(path);
|
||||
|
||||
bool actualFileExists = std::filesystem::exists(path);
|
||||
if (actualFileExists)
|
||||
{
|
||||
std::filesystem::remove(path); //clean up before compare asserts
|
||||
}
|
||||
Assert::IsFalse(actualFileExists);
|
||||
|
||||
auto devices = data.GetDeviceInfoMap();
|
||||
Assert::AreEqual((size_t)1, devices.size());
|
||||
|
||||
auto actual = devices.find(deviceId)->second;
|
||||
Assert::AreEqual(expected.showSpacing, actual.showSpacing);
|
||||
Assert::AreEqual(expected.spacing, actual.spacing);
|
||||
Assert::AreEqual(expected.zoneCount, actual.zoneCount);
|
||||
Assert::AreEqual((int)expected.activeZoneSet.type, (int)actual.activeZoneSet.type);
|
||||
Assert::AreEqual(expected.activeZoneSet.uuid.c_str(), actual.activeZoneSet.uuid.c_str());
|
||||
}
|
||||
|
||||
TEST_METHOD (DeviceInfoReadTempNonexistent)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const std::wstring path = data.zonesSettingsFileName + L".test_tmp";
|
||||
data.ParseDeviceInfoFromTmpFile(path);
|
||||
|
||||
auto devices = data.GetDeviceInfoMap();
|
||||
Assert::AreEqual((size_t)0, devices.size());
|
||||
}
|
||||
|
||||
TEST_METHOD (AppZoneHistoryParseSingle)
|
||||
{
|
||||
const std::wstring expectedAppPath = L"appPath";
|
||||
@ -1619,72 +1539,6 @@ namespace FancyZonesUnitTests
|
||||
compareJsonArrays(expected, actual);
|
||||
}
|
||||
|
||||
TEST_METHOD (CustomZoneSetsReadTemp)
|
||||
{
|
||||
//prepare device data
|
||||
const std::wstring deviceId = L"default_device_id";
|
||||
|
||||
{
|
||||
TDeviceInfoMap deviceInfoMap;
|
||||
DeviceInfoData deviceInfoData { ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 };
|
||||
deviceInfoMap.insert(std::make_pair(deviceId, deviceInfoData));
|
||||
|
||||
const std::wstring deviceInfoPath = m_fzData.zonesSettingsFileName + L".device_info_tmp";
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_defaultVDId, deviceInfoPath);
|
||||
|
||||
m_fzData.ParseDeviceInfoFromTmpFile(deviceInfoPath);
|
||||
std::filesystem::remove(deviceInfoPath);
|
||||
}
|
||||
|
||||
const std::wstring uuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}";
|
||||
const GridLayoutInfo grid(GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{
|
||||
.rows = 1,
|
||||
.columns = 3,
|
||||
.rowsPercents = { 10000 },
|
||||
.columnsPercents = { 2500, 5000, 2500 },
|
||||
.cellChildMap = { { 0, 1, 2 } } }));
|
||||
CustomZoneSetData zoneSetData{ L"name", CustomLayoutType::Grid, grid };
|
||||
CustomZoneSetJSON expected{ uuid, zoneSetData };
|
||||
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const std::wstring path = data.zonesSettingsFileName + L".test_tmp";
|
||||
|
||||
TCustomZoneSetsMap customZoneSets;
|
||||
customZoneSets.insert(std::make_pair(uuid, zoneSetData));
|
||||
JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, path);
|
||||
|
||||
m_fzData.ParseCustomZoneSetsFromTmpFile(path);
|
||||
|
||||
bool actualFileExists = std::filesystem::exists(path);
|
||||
if (actualFileExists)
|
||||
{
|
||||
std::filesystem::remove(path); //clean up before compare asserts
|
||||
}
|
||||
Assert::IsFalse(actualFileExists);
|
||||
|
||||
auto devices = m_fzData.GetCustomZoneSetsMap();
|
||||
Assert::AreEqual((size_t)1, devices.size());
|
||||
|
||||
auto actual = devices.find(uuid)->second;
|
||||
Assert::AreEqual((int)expected.data.type, (int)actual.type);
|
||||
Assert::AreEqual(expected.data.name.c_str(), actual.name.c_str());
|
||||
auto expectedGrid = std::get<GridLayoutInfo>(expected.data.info);
|
||||
auto actualGrid = std::get<GridLayoutInfo>(actual.info);
|
||||
Assert::AreEqual(expectedGrid.rows(), actualGrid.rows());
|
||||
Assert::AreEqual(expectedGrid.columns(), actualGrid.columns());
|
||||
}
|
||||
|
||||
TEST_METHOD (CustomZoneSetsReadTempNonexistent)
|
||||
{
|
||||
const std::wstring path = m_fzData.zonesSettingsFileName + L".test_tmp";
|
||||
const std::wstring deviceId = L"default_device_id";
|
||||
|
||||
m_fzData.ParseCustomZoneSetsFromTmpFile(path);
|
||||
auto devices = m_fzData.GetDeviceInfoMap();
|
||||
Assert::AreEqual((size_t)0, devices.size());
|
||||
}
|
||||
|
||||
TEST_METHOD (SetActiveZoneSet)
|
||||
{
|
||||
FancyZonesData data;
|
||||
@ -1879,6 +1733,36 @@ namespace FancyZonesUnitTests
|
||||
Assert::IsTrue(actual);
|
||||
}
|
||||
|
||||
TEST_METHOD (SaveFancyZonesDataWithTemplates)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const auto& jsonPath = data.zonesSettingsFileName;
|
||||
|
||||
// json with templates
|
||||
json::JsonObject expectedJsonObj;
|
||||
json::JsonObject templateObj = json::JsonObject::Parse(L"{\"type\": \"focus\", \"show-spacing\": false, \"spacing\": 15, \"zone-count\": 7, \"sensitivity-radius\": 25}");
|
||||
json::JsonArray templatesArray{};
|
||||
templatesArray.Append(templateObj);
|
||||
expectedJsonObj.SetNamedValue(L"devices", json::JsonArray{});
|
||||
expectedJsonObj.SetNamedValue(L"custom-zone-sets", json::JsonArray{});
|
||||
expectedJsonObj.SetNamedValue(L"templates", templatesArray);
|
||||
|
||||
// write json with templates to file
|
||||
json::to_file(jsonPath, expectedJsonObj);
|
||||
|
||||
data.SaveFancyZonesData();
|
||||
|
||||
// verify that file was written successfully
|
||||
Assert::IsTrue(std::filesystem::exists(jsonPath));
|
||||
|
||||
// verify that templates were not changed after calling SaveFancyZonesData()
|
||||
std::wstring str;
|
||||
std::wifstream { jsonPath, std::ios::binary } >> str;
|
||||
json::JsonObject actualJson = json::JsonObject::Parse(str);
|
||||
compareJsonObjects(expectedJsonObj, actualJson);
|
||||
}
|
||||
|
||||
TEST_METHOD (AppLastZoneIndex)
|
||||
{
|
||||
const std::wstring deviceId = L"device-id";
|
||||
@ -2067,4 +1951,38 @@ namespace FancyZonesUnitTests
|
||||
Assert::IsFalse(data.RemoveAppLastZone(nullptr, deviceId, zoneSetId));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CLASS(EditorArgsUnitTests)
|
||||
{
|
||||
TEST_METHOD(MonitorToJson)
|
||||
{
|
||||
const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}";
|
||||
MonitorInfo monitor{ 144, deviceId, -10, 0, true };
|
||||
|
||||
const auto expectedStr = L"{\"dpi\": 144, \"monitor-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"top-coordinate\": -10, \"left-coordinate\": 0, \"is-selected\": true}";
|
||||
const auto expected = json::JsonObject::Parse(expectedStr);
|
||||
|
||||
const auto actual = MonitorInfo::ToJson(monitor);
|
||||
|
||||
compareJsonObjects(expected, actual);
|
||||
}
|
||||
|
||||
TEST_METHOD(EditorArgsToJson)
|
||||
{
|
||||
MonitorInfo monitor1{ 144, L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}", -10, 0, true };
|
||||
MonitorInfo monitor2{ 96, L"AOC2460#4&fe3a015&0&UID65793_1920_1080_{39B25DD2-130D-4B5D-8851-4791D66B1538}", 0, 1920, false };
|
||||
EditorArgs args{
|
||||
1, true, std::vector<MonitorInfo>{ monitor1, monitor2 }
|
||||
};
|
||||
|
||||
const std::wstring expectedMonitor1 = L"{\"dpi\": 144, \"monitor-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"top-coordinate\": -10, \"left-coordinate\": 0, \"is-selected\": true}";
|
||||
const std::wstring expectedMonitor2 = L"{\"dpi\": 96, \"monitor-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1080_{39B25DD2-130D-4B5D-8851-4791D66B1538}\", \"top-coordinate\": 0, \"left-coordinate\": 1920, \"is-selected\": false}";
|
||||
const std::wstring expectedStr = L"{\"process-id\": 1, \"span-zones-across-monitors\": true, \"monitors\": [" + expectedMonitor1 + L", " + expectedMonitor2 + L"]}";
|
||||
|
||||
const auto expected = json::JsonObject::Parse(expectedStr);
|
||||
const auto actual = EditorArgs::ToJson(args);
|
||||
|
||||
compareJsonObjects(expected, actual);
|
||||
}
|
||||
};
|
||||
}
|
@ -1047,34 +1047,16 @@ namespace FancyZonesUnitTests
|
||||
TEST_METHOD (CustomZoneFromValidCanvasLayoutInfo)
|
||||
{
|
||||
//prepare device data
|
||||
{
|
||||
const std::wstring zoneUuid = L"default_device_id";
|
||||
|
||||
JSONHelpers::TDeviceInfoMap deviceInfoMap;
|
||||
deviceInfoMap.insert(std::make_pair(zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 }));
|
||||
|
||||
GUID virtualDesktopId{};
|
||||
Assert::IsTrue(VirtualDesktopUtils::GetCurrentVirtualDesktopId(&virtualDesktopId), L"Cannot create virtual desktop id");
|
||||
const std::wstring deviceInfoPath = FancyZonesDataInstance().zonesSettingsFileName + L".device_info_tmp";
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, virtualDesktopId, deviceInfoPath);
|
||||
|
||||
FancyZonesDataInstance().ParseDeviceInfoFromTmpFile(deviceInfoPath);
|
||||
std::filesystem::remove(deviceInfoPath);
|
||||
}
|
||||
const std::wstring zoneUuid = L"default_device_id";
|
||||
FancyZonesDataInstance().SetDeviceInfo(zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 });
|
||||
|
||||
//prepare expected data
|
||||
wil::unique_cotaskmem_string uuid;
|
||||
Assert::AreEqual(S_OK, StringFromCLSID(m_id, &uuid));
|
||||
const CanvasLayoutInfo info{ 123, 321, { CanvasLayoutInfo::Rect{ 0, 0, 100, 100 }, CanvasLayoutInfo::Rect{ 50, 50, 150, 150 } } };
|
||||
CustomZoneSetData zoneSetData{ L"name", CustomLayoutType::Canvas, info };
|
||||
JSONHelpers::CustomZoneSetJSON expected{ uuid.get(), zoneSetData };
|
||||
JSONHelpers::TCustomZoneSetsMap customZoneSets;
|
||||
customZoneSets.insert(std::make_pair(uuid.get(), zoneSetData));
|
||||
JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, m_path);
|
||||
|
||||
Assert::IsTrue(std::filesystem::exists(m_path));
|
||||
FancyZonesDataInstance().ParseCustomZoneSetsFromTmpFile(m_path);
|
||||
|
||||
FancyZonesDataInstance().SetCustomZonesets(uuid.get(), zoneSetData);
|
||||
|
||||
//test
|
||||
const int spacing = 10;
|
||||
const int zoneCount = static_cast<int>(info.zones.size());
|
||||
@ -1091,20 +1073,8 @@ namespace FancyZonesUnitTests
|
||||
TEST_METHOD (CustomZoneFromValidGridFullLayoutInfo)
|
||||
{
|
||||
//prepare device data
|
||||
{
|
||||
const std::wstring zoneUuid = L"default_device_id";
|
||||
|
||||
JSONHelpers::TDeviceInfoMap deviceInfoMap;
|
||||
deviceInfoMap.insert(std::make_pair(zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 }));
|
||||
|
||||
GUID virtualDesktopId{};
|
||||
Assert::IsTrue(VirtualDesktopUtils::GetCurrentVirtualDesktopId(&virtualDesktopId), L"Cannot create virtual desktop id");
|
||||
const std::wstring deviceInfoPath = FancyZonesDataInstance().zonesSettingsFileName + L".device_info_tmp";
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, virtualDesktopId, deviceInfoPath);
|
||||
|
||||
FancyZonesDataInstance().ParseDeviceInfoFromTmpFile(deviceInfoPath);
|
||||
std::filesystem::remove(deviceInfoPath);
|
||||
}
|
||||
const std::wstring zoneUuid = L"default_device_id";
|
||||
FancyZonesDataInstance().SetDeviceInfo(zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 });
|
||||
|
||||
//prepare expected data
|
||||
wil::unique_cotaskmem_string uuid;
|
||||
@ -1116,13 +1086,7 @@ namespace FancyZonesUnitTests
|
||||
.columnsPercents = { 2500, 5000, 2500 },
|
||||
.cellChildMap = { { 0, 1, 2 } } }));
|
||||
CustomZoneSetData zoneSetData{ L"name", CustomLayoutType::Grid, grid };
|
||||
JSONHelpers::CustomZoneSetJSON expected{ uuid.get(), zoneSetData };
|
||||
JSONHelpers::TCustomZoneSetsMap customZoneSets;
|
||||
customZoneSets.insert(std::make_pair(uuid.get(), zoneSetData));
|
||||
JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, m_path);
|
||||
|
||||
Assert::IsTrue(std::filesystem::exists(m_path));
|
||||
FancyZonesDataInstance().ParseCustomZoneSetsFromTmpFile(m_path);
|
||||
FancyZonesDataInstance().SetCustomZonesets(uuid.get(), zoneSetData);
|
||||
|
||||
const int spacing = 10;
|
||||
const int zoneCount = grid.rows() * grid.columns();
|
||||
|
@ -175,225 +175,9 @@ namespace FancyZonesUnitTests
|
||||
Assert::AreEqual(activeZoneSet->GetZones().size(), static_cast<size_t>(3));
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateZoneWindowWithActiveZoneTmpFile)
|
||||
{
|
||||
using namespace FancyZonesDataTypes;
|
||||
|
||||
const auto activeZoneSetTempPath = m_fancyZonesData.activeZoneSetTmpFileName;
|
||||
|
||||
for (int type = static_cast<int>(ZoneSetLayoutType::Focus); type < static_cast<int>(ZoneSetLayoutType::Custom); type++)
|
||||
{
|
||||
const auto expectedZoneSet = ZoneSetData{ Helpers::CreateGuidString(), static_cast<ZoneSetLayoutType>(type) };
|
||||
const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 };
|
||||
const auto deviceInfo = JSONHelpers::DeviceInfoJSON{ m_uniqueId.str(), data };
|
||||
const auto json = JSONHelpers::DeviceInfoJSON::ToJson(deviceInfo);
|
||||
json::to_file(activeZoneSetTempPath, json);
|
||||
|
||||
m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath);
|
||||
|
||||
//temp file read on initialization
|
||||
auto actual = MakeZoneWindow(winrt::make_self<MockZoneWindowHost>().get(), m_hInst, m_monitor, m_uniqueId.str(), {});
|
||||
|
||||
testZoneWindow(actual);
|
||||
|
||||
Assert::IsNotNull(actual->ActiveZoneSet());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateZoneWindowWithActiveCustomZoneTmpFile)
|
||||
{
|
||||
using namespace FancyZonesDataTypes;
|
||||
|
||||
const auto activeZoneSetTempPath = m_fancyZonesData.activeZoneSetTmpFileName;
|
||||
|
||||
const ZoneSetLayoutType type = ZoneSetLayoutType::Custom;
|
||||
const auto expectedZoneSet = ZoneSetData{ Helpers::CreateGuidString(), type };
|
||||
const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 };
|
||||
JSONHelpers::TDeviceInfoMap deviceInfoMap;
|
||||
deviceInfoMap.insert(std::make_pair(m_uniqueId.str(), data));
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_virtualDesktopGuid, activeZoneSetTempPath);
|
||||
|
||||
m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath);
|
||||
|
||||
//temp file read on initialization
|
||||
auto actual = MakeZoneWindow(winrt::make_self<MockZoneWindowHost>().get(), m_hInst, m_monitor, m_uniqueId.str(), {});
|
||||
|
||||
testZoneWindow(actual);
|
||||
|
||||
//custom zone needs temp file for applied zone
|
||||
Assert::IsNotNull(actual->ActiveZoneSet());
|
||||
const auto actualZoneSet = actual->ActiveZoneSet()->GetZones();
|
||||
Assert::AreEqual((size_t)0, actualZoneSet.size());
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateZoneWindowWithActiveCustomZoneAppliedTmpFile)
|
||||
{
|
||||
using namespace FancyZonesDataTypes;
|
||||
|
||||
//save required data
|
||||
const auto activeZoneSetTempPath = m_fancyZonesData.activeZoneSetTmpFileName;
|
||||
const auto appliedZoneSetTempPath = m_fancyZonesData.appliedZoneSetTmpFileName;
|
||||
|
||||
const ZoneSetLayoutType type = ZoneSetLayoutType::Custom;
|
||||
const auto customSetGuid = Helpers::CreateGuidString();
|
||||
const auto expectedZoneSet = ZoneSetData{ customSetGuid, type };
|
||||
const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 };
|
||||
JSONHelpers::TDeviceInfoMap deviceInfoMap;
|
||||
deviceInfoMap.insert(std::make_pair(m_uniqueId.str(), data));
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_virtualDesktopGuid, activeZoneSetTempPath);
|
||||
|
||||
const auto info = CanvasLayoutInfo{
|
||||
100, 100, std::vector{ CanvasLayoutInfo::Rect{ 0, 0, 100, 100 } }
|
||||
};
|
||||
const auto customZoneData = CustomZoneSetData{ L"name", CustomLayoutType::Canvas, info };
|
||||
auto customZoneJson = JSONHelpers::CustomZoneSetJSON::ToJson(JSONHelpers::CustomZoneSetJSON{ customSetGuid, customZoneData });
|
||||
JSONHelpers::TCustomZoneSetsMap customZoneSets;
|
||||
customZoneSets.insert(std::make_pair(customSetGuid, customZoneData));
|
||||
JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, appliedZoneSetTempPath);
|
||||
m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath);
|
||||
m_fancyZonesData.ParseCustomZoneSetsFromTmpFile(appliedZoneSetTempPath);
|
||||
|
||||
//temp file read on initialization
|
||||
auto actual = MakeZoneWindow(winrt::make_self<MockZoneWindowHost>().get(), m_hInst, m_monitor, m_uniqueId.str(), {});
|
||||
|
||||
testZoneWindow(actual);
|
||||
|
||||
//custom zone needs temp file for applied zone
|
||||
Assert::IsNotNull(actual->ActiveZoneSet());
|
||||
const auto actualZoneSet = actual->ActiveZoneSet()->GetZones();
|
||||
Assert::AreEqual((size_t)1, actualZoneSet.size());
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateZoneWindowWithActiveCustomZoneAppliedTmpFileWithDeletedCustomZones)
|
||||
{
|
||||
using namespace FancyZonesDataTypes;
|
||||
|
||||
//save required data
|
||||
const auto activeZoneSetTempPath = m_fancyZonesData.activeZoneSetTmpFileName;
|
||||
const auto appliedZoneSetTempPath = m_fancyZonesData.appliedZoneSetTmpFileName;
|
||||
const auto deletedZonesTempPath = m_fancyZonesData.deletedCustomZoneSetsTmpFileName;
|
||||
|
||||
const ZoneSetLayoutType type = ZoneSetLayoutType::Custom;
|
||||
const auto customSetGuid = Helpers::CreateGuidString();
|
||||
const auto expectedZoneSet = ZoneSetData{ customSetGuid, type };
|
||||
const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 };
|
||||
JSONHelpers::TDeviceInfoMap deviceInfoMap;
|
||||
deviceInfoMap.insert(std::make_pair(m_uniqueId.str(), data));
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_virtualDesktopGuid, activeZoneSetTempPath);
|
||||
|
||||
const auto info = CanvasLayoutInfo{
|
||||
100, 100, std::vector{ CanvasLayoutInfo::Rect{ 0, 0, 100, 100 } }
|
||||
};
|
||||
const auto customZoneData = CustomZoneSetData{ L"name", CustomLayoutType::Canvas, info };
|
||||
const auto customZoneSet = JSONHelpers::CustomZoneSetJSON{ customSetGuid, customZoneData };
|
||||
auto customZoneJson = JSONHelpers::CustomZoneSetJSON::ToJson(customZoneSet);
|
||||
JSONHelpers::TCustomZoneSetsMap customZoneSets;
|
||||
customZoneSets.insert(std::make_pair(customSetGuid, customZoneData));
|
||||
JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, appliedZoneSetTempPath);
|
||||
|
||||
//save same zone as deleted
|
||||
json::JsonObject deletedCustomZoneSets = {};
|
||||
json::JsonArray zonesArray{};
|
||||
zonesArray.Append(json::JsonValue::CreateStringValue(customZoneSet.uuid.substr(1, customZoneSet.uuid.size() - 2).c_str()));
|
||||
deletedCustomZoneSets.SetNamedValue(L"deleted-custom-zone-sets", zonesArray);
|
||||
json::to_file(deletedZonesTempPath, deletedCustomZoneSets);
|
||||
|
||||
m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath);
|
||||
m_fancyZonesData.ParseDeletedCustomZoneSetsFromTmpFile(deletedZonesTempPath);
|
||||
m_fancyZonesData.ParseCustomZoneSetsFromTmpFile(appliedZoneSetTempPath);
|
||||
|
||||
//temp file read on initialization
|
||||
auto actual = MakeZoneWindow(winrt::make_self<MockZoneWindowHost>().get(), m_hInst, m_monitor, m_uniqueId.str(), {});
|
||||
|
||||
testZoneWindow(actual);
|
||||
|
||||
Assert::IsNotNull(actual->ActiveZoneSet());
|
||||
const auto actualZoneSet = actual->ActiveZoneSet()->GetZones();
|
||||
Assert::AreEqual((size_t)1, actualZoneSet.size());
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateZoneWindowWithActiveCustomZoneAppliedTmpFileWithUnusedDeletedCustomZones)
|
||||
{
|
||||
using namespace FancyZonesDataTypes;
|
||||
|
||||
//save required data
|
||||
const auto activeZoneSetTempPath = m_fancyZonesData.activeZoneSetTmpFileName;
|
||||
const auto appliedZoneSetTempPath = m_fancyZonesData.appliedZoneSetTmpFileName;
|
||||
const auto deletedZonesTempPath = m_fancyZonesData.deletedCustomZoneSetsTmpFileName;
|
||||
|
||||
const ZoneSetLayoutType type = ZoneSetLayoutType::Custom;
|
||||
const auto customSetGuid = Helpers::CreateGuidString();
|
||||
const auto expectedZoneSet = ZoneSetData{ customSetGuid, type };
|
||||
const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 };
|
||||
JSONHelpers::TDeviceInfoMap deviceInfoMap;
|
||||
deviceInfoMap.insert(std::make_pair(m_uniqueId.str(), data));
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, m_virtualDesktopGuid, activeZoneSetTempPath);
|
||||
|
||||
const auto info = CanvasLayoutInfo{
|
||||
100, 100, std::vector{ CanvasLayoutInfo::Rect{ 0, 0, 100, 100 } }
|
||||
};
|
||||
const auto customZoneData = CustomZoneSetData{ L"name", CustomLayoutType::Canvas, info };
|
||||
const auto customZoneSet = JSONHelpers::CustomZoneSetJSON{ customSetGuid, customZoneData };
|
||||
auto customZoneJson = JSONHelpers::CustomZoneSetJSON::ToJson(customZoneSet);
|
||||
JSONHelpers::TCustomZoneSetsMap customZoneSets;
|
||||
customZoneSets.insert(std::make_pair(customSetGuid, customZoneData));
|
||||
JSONHelpers::SerializeCustomZoneSetsToTmpFile(customZoneSets, appliedZoneSetTempPath);
|
||||
|
||||
//save different zone as deleted
|
||||
json::JsonObject deletedCustomZoneSets = {};
|
||||
json::JsonArray zonesArray{};
|
||||
const auto uuid = Helpers::CreateGuidString();
|
||||
zonesArray.Append(json::JsonValue::CreateStringValue(uuid.substr(1, uuid.size() - 2).c_str()));
|
||||
deletedCustomZoneSets.SetNamedValue(L"deleted-custom-zone-sets", zonesArray);
|
||||
json::to_file(deletedZonesTempPath, deletedCustomZoneSets);
|
||||
|
||||
m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath);
|
||||
m_fancyZonesData.ParseDeletedCustomZoneSetsFromTmpFile(deletedZonesTempPath);
|
||||
m_fancyZonesData.ParseCustomZoneSetsFromTmpFile(appliedZoneSetTempPath);
|
||||
|
||||
//temp file read on initialization
|
||||
auto actual = MakeZoneWindow(winrt::make_self<MockZoneWindowHost>().get(), m_hInst, m_monitor, m_uniqueId.str(), {});
|
||||
|
||||
testZoneWindow(actual);
|
||||
|
||||
Assert::IsNotNull(actual->ActiveZoneSet());
|
||||
const auto actualZoneSet = actual->ActiveZoneSet()->GetZones();
|
||||
Assert::AreEqual((size_t)1, actualZoneSet.size());
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateZoneWindowClonedFromParent)
|
||||
{
|
||||
using namespace FancyZonesDataTypes;
|
||||
|
||||
const ZoneSetLayoutType type = ZoneSetLayoutType::PriorityGrid;
|
||||
const int spacing = 10;
|
||||
const int zoneCount = 5;
|
||||
const auto customSetGuid = Helpers::CreateGuidString();
|
||||
const auto parentZoneSet = ZoneSetData{ customSetGuid, type };
|
||||
const auto parentDeviceInfo = DeviceInfoData{ parentZoneSet, true, spacing, zoneCount };
|
||||
m_fancyZonesData.SetDeviceInfo(m_parentUniqueId.str(), parentDeviceInfo);
|
||||
|
||||
winrt::com_ptr<MockZoneWindowHost> zoneWindowHost = winrt::make_self<MockZoneWindowHost>();
|
||||
auto parentZoneWindow = MakeZoneWindow(zoneWindowHost.get(), m_hInst, m_monitor, m_parentUniqueId.str(), {});
|
||||
zoneWindowHost->m_zoneWindow = parentZoneWindow.get();
|
||||
|
||||
// newWorkArea = true - zoneWindow will be cloned from parent
|
||||
auto actualZoneWindow = MakeZoneWindow(winrt::make_self<MockZoneWindowHost>().get(), m_hInst, m_monitor, m_uniqueId.str(), m_parentUniqueId.str());
|
||||
|
||||
Assert::IsNotNull(actualZoneWindow->ActiveZoneSet());
|
||||
const auto actualZoneSet = actualZoneWindow->ActiveZoneSet()->GetZones();
|
||||
Assert::AreEqual((size_t)zoneCount, actualZoneSet.size());
|
||||
|
||||
Assert::IsTrue(m_fancyZonesData.GetDeviceInfoMap().contains(m_uniqueId.str()));
|
||||
auto currentDeviceInfo = m_fancyZonesData.GetDeviceInfoMap().at(m_uniqueId.str());
|
||||
Assert::AreEqual(zoneCount, currentDeviceInfo.zoneCount);
|
||||
Assert::AreEqual(spacing, currentDeviceInfo.spacing);
|
||||
Assert::AreEqual(static_cast<int>(type), static_cast<int>(currentDeviceInfo.activeZoneSet.type));
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateZoneWindowNotClonedFromParent)
|
||||
{
|
||||
using namespace FancyZonesDataTypes;
|
||||
TEST_METHOD (CreateZoneWindowClonedFromParent)
|
||||
{
|
||||
using namespace FancyZonesDataTypes;
|
||||
|
||||
const ZoneSetLayoutType type = ZoneSetLayoutType::PriorityGrid;
|
||||
const int spacing = 10;
|
||||
|
Loading…
Reference in New Issue
Block a user