mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
FancyZones and Shortcut Guide initial commit
Co-authored-by: Alexis Campailla <alexis@janeasystems.com> Co-authored-by: Bret Anderson <bretan@microsoft.com> Co-authored-by: Enrico Giordani <enrico.giordani@gmail.com> Co-authored-by: Jaime Bernardo <jaime@janeasystems.com> Co-authored-by: Jeff Bogdan <jeffbog@microsoft.com> Co-authored-by: March Rogers <marchr@microsoft.com> Co-authored-by: Mike Harsh <mharsh@microsoft.com> Co-authored-by: Nachum Bundak <Nachum.Bundak@microsoft.com> Co-authored-by: Oliver Jones <ojones@microsoft.com> Co-authored-by: Patrick Little <plittle@microsoft.com>
This commit is contained in:
committed by
Bartosz Sosnowski
parent
10c5396099
commit
8431b80e48
25
src/modules/fancyzones/editor/FancyZonesEditor.sln
Normal file
25
src/modules/fancyzones/editor/FancyZonesEditor.sln
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27703.2042
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZonesEditor", "FancyZonesEditor\FancyZonesEditor.csproj", "{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {9A90742C-8AA0-4A56-A01F-70C8754B4684}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
17
src/modules/fancyzones/editor/FancyZonesEditor/App.xaml
Normal file
17
src/modules/fancyzones/editor/FancyZonesEditor/App.xaml
Normal file
@@ -0,0 +1,17 @@
|
||||
<Application x:Class="FancyZonesEditor.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:FancyZonesEditor"
|
||||
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" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
74
src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs
Normal file
74
src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using FancyZonesEditor;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
public Settings ZoneSettings { get { return _settings; } }
|
||||
private Settings _settings;
|
||||
private ushort _idInitial = 0;
|
||||
public App()
|
||||
{
|
||||
//init settings
|
||||
_settings = new Settings();
|
||||
}
|
||||
|
||||
private void OnStartup(object sender, StartupEventArgs e)
|
||||
{
|
||||
if (e.Args.Length > 1)
|
||||
{
|
||||
UInt16.TryParse(e.Args[1], out _idInitial);
|
||||
}
|
||||
|
||||
LayoutModel foundModel = null;
|
||||
|
||||
if (_idInitial != 0)
|
||||
{
|
||||
foreach (LayoutModel model in _settings.DefaultModels)
|
||||
{
|
||||
if (model.Id == _idInitial)
|
||||
{
|
||||
// found match
|
||||
foundModel = model;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundModel == null)
|
||||
{
|
||||
foreach (LayoutModel model in _settings.CustomModels)
|
||||
{
|
||||
if (model.Id == _idInitial)
|
||||
{
|
||||
// found match
|
||||
foundModel = model;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (foundModel == null)
|
||||
{
|
||||
foundModel = _settings.DefaultModels[0];
|
||||
}
|
||||
|
||||
foundModel.IsSelected = true;
|
||||
// TODO: multimon
|
||||
// Pass in the correct args to show on the desired monitor
|
||||
EditorOverlay overlay = new EditorOverlay();
|
||||
overlay.Show();
|
||||
overlay.DataContext = foundModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<UserControl x:Class="FancyZonesEditor.CanvasEditor"
|
||||
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:local="clr-namespace:FancyZonesEditor"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300" d:DesignWidth="300">
|
||||
<Grid>
|
||||
<Canvas x:Name="Preview"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for CanvasEditor.xaml
|
||||
/// </summary>
|
||||
public partial class CanvasEditor : UserControl
|
||||
{
|
||||
public CanvasEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += CanvasEditor_Loaded;
|
||||
}
|
||||
|
||||
private void CanvasEditor_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CanvasLayoutModel model = (CanvasLayoutModel)DataContext;
|
||||
if (model != null)
|
||||
{
|
||||
Model = model;
|
||||
UpdateZoneRects();
|
||||
|
||||
model.PropertyChanged += OnModelChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnModelChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Zones")
|
||||
{
|
||||
UpdateZoneRects();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateZoneRects()
|
||||
{
|
||||
UIElementCollection previewChildren = Preview.Children;
|
||||
int previewChildrenCount = previewChildren.Count;
|
||||
while (previewChildrenCount < Model.Zones.Count)
|
||||
{
|
||||
CanvasZone zone = new CanvasZone();
|
||||
zone.Model = Model;
|
||||
Preview.Children.Add(zone);
|
||||
previewChildrenCount++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < previewChildrenCount; i++)
|
||||
{
|
||||
Int32Rect rect = Model.Zones[i];
|
||||
CanvasZone zone = previewChildren[i] as CanvasZone;
|
||||
|
||||
zone.ZoneIndex = i;
|
||||
Canvas.SetLeft(zone, rect.X);
|
||||
Canvas.SetTop(zone, rect.Y);
|
||||
zone.MinHeight = rect.Height;
|
||||
zone.MinWidth = rect.Width;
|
||||
}
|
||||
}
|
||||
|
||||
public CanvasLayoutModel Model;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
<local:EditorWindow x:Class="FancyZonesEditor.CanvasEditorWindow"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
Title=""
|
||||
Width="528"
|
||||
SizeToContent="Height"
|
||||
Background="White"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Closed="OnClosed">
|
||||
|
||||
|
||||
<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="secondaryButton" 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="Padding" Value="0,5,0,5"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="#F2F2F2"/>
|
||||
<Setter Property="Margin" Value="16,10,0,0" />
|
||||
<Setter Property="Width" Value="239"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<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="#BCBCBD"/>
|
||||
</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="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="#cccccc"/>
|
||||
<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>
|
||||
<TextBlock Name="windowEditorDialogTitle" Text="Custom layout creator" Style="{StaticResource titleText}" />
|
||||
<Button x:Name="newZoneButton" Width="496" Height="136" Style="{StaticResource newZoneButton}" Click="OnAddZone">
|
||||
<StackPanel>
|
||||
<TextBlock x:Name="newSoneName" Text="Add new zone" Style="{StaticResource templateTitleText}" />
|
||||
<TextBlock HorizontalAlignment="Center" Text="+" Margin="0,-40,0,0"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<TextBlock Text="Name" Style="{StaticResource textLabel}" />
|
||||
<TextBox Text="{Binding Name}" 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}"/>
|
||||
</StackPanel>
|
||||
-->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,12,0,16">
|
||||
<Button Content="Cancel" Style="{StaticResource secondaryButton}" Click="OnCancel"/>
|
||||
<Button Content="Save and apply" Style="{StaticResource primaryButton}" Click="OnSaveApplyTemplate" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:EditorWindow>
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using MahApps.Metro.Controls;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for windowEditor.xaml
|
||||
/// </summary>
|
||||
public partial class CanvasEditorWindow : EditorWindow
|
||||
{
|
||||
public CanvasEditorWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
Model = EditorOverlay.Current.DataContext as CanvasLayoutModel;
|
||||
}
|
||||
|
||||
private void OnAddZone(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Model.AddZone(new Int32Rect(_offset, _offset, (int) (Model.ReferenceWidth * 0.6), (int) (Model.ReferenceHeight * 0.6)));
|
||||
_offset += 100;
|
||||
}
|
||||
|
||||
private int _offset = 100;
|
||||
private CanvasLayoutModel Model;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<UserControl x:Class="FancyZonesEditor.CanvasZone"
|
||||
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:local="clr-namespace:FancyZonesEditor"
|
||||
mc:Ignorable="d"
|
||||
Background="LightGray"
|
||||
Opacity="0.75"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid x:Name="Frame">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="8"/>
|
||||
<RowDefinition Height="16"/>
|
||||
<RowDefinition Height="24"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="16"/>
|
||||
<RowDefinition Height="8"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="8"/>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<ColumnDefinition Width="8"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Thumb x:Name="NWResize" Cursor="SizeNWSE" Background="Black" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" DragDelta="NWResize_DragDelta"/>
|
||||
<Thumb x:Name="NEResize" Cursor="SizeNESW" Background="Black" Grid.Row="0" Grid.Column="3" Grid.RowSpan="2" Grid.ColumnSpan="2" DragDelta="NEResize_DragDelta"/>
|
||||
<Thumb x:Name="SWResize" Cursor="SizeNESW" Background="Black" Grid.Row="4" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" DragDelta="SWResize_DragDelta"/>
|
||||
<Thumb x:Name="SEResize" Cursor="SizeNWSE" Background="Black" Grid.Row="4" Grid.Column="3" Grid.RowSpan="2" Grid.ColumnSpan="2" DragDelta="SEResize_DragDelta"/>
|
||||
<Thumb x:Name="NResize" Cursor="SizeNS" Background="Black" Margin="1,0,1,0" Grid.Row="0" Grid.Column="2" DragDelta="NResize_DragDelta"/>
|
||||
<Thumb x:Name="SResize" Cursor="SizeNS" Background="Black" Margin="1,0,1,0" Grid.Row="5" Grid.Column="2" DragDelta="SResize_DragDelta"/>
|
||||
<Thumb x:Name="WResize" Cursor="SizeWE" Background="Black" Margin="0,1,0,1" Grid.Row="2" Grid.Column="0" Grid.RowSpan="2" DragDelta="WResize_DragDelta"/>
|
||||
<Thumb x:Name="EResize" Cursor="SizeWE" Background="Black" Margin="0,1,0,1" Grid.Row="2" Grid.Column="4" Grid.RowSpan="2" DragDelta="EResize_DragDelta"/>
|
||||
<DockPanel Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" Grid.ColumnSpan="3">
|
||||
<Button DockPanel.Dock="Right" Padding="8,0" Click="OnClose">
|
||||
<Image Source="images/ChromeClose.png" Height="24" Width="24" />
|
||||
</Button>
|
||||
<Thumb x:Name="Caption" Cursor="SizeAll" Background="DarkGray" DragDelta="Caption_DragDelta"/>
|
||||
</DockPanel>
|
||||
<Rectangle Fill="LightGray" Grid.Row="3" Grid.Column="1" Grid.RowSpan="2" Grid.ColumnSpan="3"/>
|
||||
<Canvas x:Name="Body" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,167 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Once you've "Committ"ed the starter grid, then the Zones within the grid come to life for you to be able to further subdivide them
|
||||
/// using splitters
|
||||
/// </summary>
|
||||
|
||||
public partial class CanvasZone : UserControl
|
||||
{
|
||||
public CanvasZone()
|
||||
{
|
||||
InitializeComponent();
|
||||
Canvas.SetZIndex(this, c_zIndex++);
|
||||
}
|
||||
|
||||
public CanvasLayoutModel Model;
|
||||
public int ZoneIndex;
|
||||
|
||||
private Point Move(double xDelta, double yDelta)
|
||||
{
|
||||
Int32Rect rect = Model.Zones[ZoneIndex];
|
||||
if (xDelta < 0)
|
||||
{
|
||||
xDelta = Math.Max(xDelta, -rect.X);
|
||||
}
|
||||
else if (xDelta > 0)
|
||||
{
|
||||
xDelta = Math.Min(xDelta, c_workArea.Width - rect.Width - rect.X);
|
||||
}
|
||||
|
||||
if (yDelta < 0)
|
||||
{
|
||||
yDelta = Math.Max(yDelta, -rect.Y);
|
||||
}
|
||||
else if (yDelta > 0)
|
||||
{
|
||||
yDelta = Math.Min(yDelta, c_workArea.Height - rect.Height - rect.Y);
|
||||
}
|
||||
|
||||
rect.X += (int) xDelta;
|
||||
rect.Y += (int) yDelta;
|
||||
|
||||
Canvas.SetLeft(this, rect.X);
|
||||
Canvas.SetTop(this, rect.Y);
|
||||
Model.Zones[ZoneIndex] = rect;
|
||||
return new Point(xDelta, yDelta);
|
||||
}
|
||||
|
||||
private void Size(double xDelta, double yDelta)
|
||||
{
|
||||
Int32Rect rect = Model.Zones[ZoneIndex];
|
||||
if (xDelta != 0)
|
||||
{
|
||||
int newWidth = rect.Width + (int) xDelta;
|
||||
|
||||
if (newWidth < 48)
|
||||
{
|
||||
newWidth = 48;
|
||||
}
|
||||
else if (newWidth > (c_workArea.Width - rect.X))
|
||||
{
|
||||
newWidth = (int) c_workArea.Width - rect.X;
|
||||
}
|
||||
MinWidth = rect.Width = newWidth;
|
||||
}
|
||||
|
||||
if (yDelta != 0)
|
||||
{
|
||||
int newHeight = rect.Height + (int)yDelta;
|
||||
|
||||
if (newHeight < 48)
|
||||
{
|
||||
newHeight = 48;
|
||||
}
|
||||
else if (newHeight > (c_workArea.Height - rect.Y))
|
||||
{
|
||||
newHeight = (int)c_workArea.Height - rect.Y;
|
||||
}
|
||||
MinHeight = rect.Height = newHeight;
|
||||
}
|
||||
Model.Zones[ZoneIndex] = rect;
|
||||
}
|
||||
|
||||
private static int c_zIndex = 0;
|
||||
|
||||
// TODO: multimon
|
||||
// This needs to be the work area of the monitor we get launched on
|
||||
private static Rect c_workArea = System.Windows.SystemParameters.WorkArea;
|
||||
|
||||
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
|
||||
{
|
||||
Canvas.SetZIndex(this, c_zIndex++);
|
||||
base.OnPreviewMouseDown(e);
|
||||
}
|
||||
private void NWResize_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
||||
{
|
||||
Point actualChange = Move(e.HorizontalChange, e.VerticalChange);
|
||||
Size(-actualChange.X, -actualChange.Y);
|
||||
}
|
||||
|
||||
private void NEResize_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
||||
{
|
||||
Point actualChange = Move(0, e.VerticalChange);
|
||||
Size(e.HorizontalChange, -actualChange.Y);
|
||||
}
|
||||
|
||||
private void SWResize_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
||||
{
|
||||
Point actualChange = Move(e.HorizontalChange, 0);
|
||||
Size(-actualChange.X, e.VerticalChange);
|
||||
}
|
||||
|
||||
private void SEResize_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
||||
{
|
||||
Size(e.HorizontalChange, e.VerticalChange);
|
||||
}
|
||||
|
||||
private void NResize_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
||||
{
|
||||
Point actualChange = Move(0, e.VerticalChange);
|
||||
Size(0, -actualChange.Y);
|
||||
}
|
||||
|
||||
private void SResize_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
||||
{
|
||||
Size(0, e.VerticalChange);
|
||||
}
|
||||
|
||||
private void WResize_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
||||
{
|
||||
Point actualChange = Move(e.HorizontalChange, 0);
|
||||
Size(-actualChange.X, 0);
|
||||
}
|
||||
|
||||
private void EResize_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
||||
{
|
||||
Size(e.HorizontalChange, 0);
|
||||
}
|
||||
|
||||
private void Caption_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
||||
{
|
||||
Move(e.HorizontalChange, e.VerticalChange);
|
||||
}
|
||||
|
||||
private void OnClose(object sender, RoutedEventArgs e)
|
||||
{
|
||||
((Panel)Parent).Children.Remove(this);
|
||||
Model.RemoveZoneAt(ZoneIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<Window x:Class="FancyZonesEditor.EditorOverlay"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
Title="Window1" Height="450" Width="800"
|
||||
ShowInTaskbar="False"
|
||||
ResizeMode="NoResize"
|
||||
WindowStyle="None"
|
||||
AllowsTransparency="True"
|
||||
Background="Transparent"
|
||||
Loaded="onLoad"/>
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
using FancyZonesEditor.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Security.RightsManagement;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for Window1.xaml
|
||||
/// </summary>
|
||||
public partial class EditorOverlay : Window
|
||||
{
|
||||
public Int32Rect[] GetZoneRects()
|
||||
{
|
||||
// TODO: the ideal here is that the ArrangeRects logic is entirely inside the model, so we don't have to walk the UIElement children to get the rect info
|
||||
Panel previewPanel = null;
|
||||
|
||||
if (_editor != null)
|
||||
{
|
||||
GridEditor gridEditor = _editor as GridEditor;
|
||||
if (gridEditor != null)
|
||||
{
|
||||
previewPanel = gridEditor.PreviewPanel;
|
||||
}
|
||||
else
|
||||
{
|
||||
//CanvasEditor
|
||||
previewPanel = ((CanvasEditor)_editor).Preview;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
previewPanel = _layoutPreview.PreviewPanel;
|
||||
}
|
||||
|
||||
var count = previewPanel.Children.Count;
|
||||
Int32Rect[] zones = new Int32Rect[count];
|
||||
|
||||
int i = 0;
|
||||
foreach (FrameworkElement child in previewPanel.Children)
|
||||
{
|
||||
Point topLeft = child.TransformToAncestor(previewPanel).Transform(new Point());
|
||||
|
||||
var right = topLeft.X + child.ActualWidth;
|
||||
var bottom = topLeft.Y + child.ActualHeight;
|
||||
zones[i].X = (int)topLeft.X;
|
||||
zones[i].Y = (int)topLeft.Y;
|
||||
zones[i].Width = (int)child.ActualWidth;
|
||||
zones[i].Height = (int)child.ActualHeight;
|
||||
i++;
|
||||
}
|
||||
|
||||
return zones;
|
||||
}
|
||||
|
||||
public static EditorOverlay Current;
|
||||
public EditorOverlay()
|
||||
{
|
||||
InitializeComponent();
|
||||
Current = this;
|
||||
|
||||
// TODO: multimon
|
||||
// Need to set Left and Top to the correct monitor based on the
|
||||
// foreground window passed in the command line arguments
|
||||
Rect workArea = System.Windows.SystemParameters.WorkArea;
|
||||
Left = workArea.Left;
|
||||
Top = workArea.Top;
|
||||
Width = workArea.Width;
|
||||
Height = workArea.Height;
|
||||
}
|
||||
|
||||
void onLoad(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ShowLayoutPicker();
|
||||
}
|
||||
|
||||
public void ShowLayoutPicker()
|
||||
{
|
||||
DataContext = null;
|
||||
|
||||
_editor = null;
|
||||
_layoutPreview = new LayoutPreview();
|
||||
_layoutPreview.IsActualSize = true;
|
||||
_layoutPreview.Opacity = 0.5;
|
||||
Content = _layoutPreview;
|
||||
|
||||
MainWindow window = new MainWindow();
|
||||
window.Owner = this;
|
||||
window.Show();
|
||||
}
|
||||
|
||||
// These event handlers are used to track the current state of the Shift and Ctrl keys on the keyboard
|
||||
// They reflect that current state into properties on the Settings object, which the Zone view will listen to in editing mode
|
||||
protected override void OnPreviewKeyDown(KeyEventArgs e)
|
||||
{
|
||||
_settings.IsShiftKeyPressed = Keyboard.Modifiers.HasFlag(ModifierKeys.Shift);
|
||||
_settings.IsCtrlKeyPressed = Keyboard.Modifiers.HasFlag(ModifierKeys.Control);
|
||||
base.OnPreviewKeyDown(e);
|
||||
}
|
||||
|
||||
protected override void OnPreviewKeyUp(KeyEventArgs e)
|
||||
{
|
||||
_settings.IsShiftKeyPressed = Keyboard.Modifiers.HasFlag(ModifierKeys.Shift);
|
||||
_settings.IsCtrlKeyPressed = Keyboard.Modifiers.HasFlag(ModifierKeys.Control);
|
||||
base.OnPreviewKeyUp(e);
|
||||
}
|
||||
|
||||
public void Edit()
|
||||
{
|
||||
_layoutPreview = null;
|
||||
if (DataContext is GridLayoutModel)
|
||||
{
|
||||
_editor = new GridEditor();
|
||||
}
|
||||
else if (DataContext is CanvasLayoutModel)
|
||||
{
|
||||
_editor = new CanvasEditor();
|
||||
}
|
||||
Content = _editor;
|
||||
}
|
||||
|
||||
private Settings _settings = ((App)Application.Current).ZoneSettings;
|
||||
private LayoutPreview _layoutPreview;
|
||||
private UserControl _editor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using FancyZonesEditor.Models;
|
||||
using MahApps.Metro.Controls;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
public class EditorWindow : MetroWindow
|
||||
{
|
||||
protected void OnSaveApplyTemplate(object sender, RoutedEventArgs e)
|
||||
{
|
||||
EditorOverlay mainEditor = EditorOverlay.Current;
|
||||
LayoutModel model = mainEditor.DataContext as LayoutModel;
|
||||
if (model != null)
|
||||
{
|
||||
model.Persist(mainEditor.GetZoneRects());
|
||||
}
|
||||
_choosing = true;
|
||||
this.Close();
|
||||
EditorOverlay.Current.Close();
|
||||
}
|
||||
|
||||
protected void OnClosed(object sender, EventArgs e)
|
||||
{
|
||||
if (!_choosing)
|
||||
{
|
||||
EditorOverlay.Current.ShowLayoutPicker();
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnCancel(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_choosing = true;
|
||||
this.Close();
|
||||
EditorOverlay.Current.ShowLayoutPicker();
|
||||
}
|
||||
|
||||
private bool _choosing = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>FancyZonesEditor</RootNamespace>
|
||||
<AssemblyName>FancyZonesEditor</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\..\..\..\..\x64\Debug\modules\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\modules\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="CanvasEditor.xaml.cs">
|
||||
<DependentUpon>CanvasEditor.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="EditorWindow.cs" />
|
||||
<Compile Include="GridEditor.xaml.cs">
|
||||
<DependentUpon>GridEditor.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="GridResizer.xaml.cs">
|
||||
<DependentUpon>GridResizer.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LayoutPreview.xaml.cs">
|
||||
<DependentUpon>LayoutPreview.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Models\CanvasLayoutModel.cs" />
|
||||
<Compile Include="Models\GridLayoutModel.cs" />
|
||||
<Compile Include="Models\LayoutModel.cs" />
|
||||
<Compile Include="Models\Settings.cs" />
|
||||
<Compile Include="EditorOverlay.xaml.cs">
|
||||
<DependentUpon>EditorOverlay.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="RowColInfo.cs" />
|
||||
<Compile Include="GridEditorWindow.xaml.cs">
|
||||
<DependentUpon>GridEditorWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WindowLayout.xaml.cs">
|
||||
<DependentUpon>WindowLayout.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="CanvasEditorWindow.xaml.cs">
|
||||
<DependentUpon>CanvasEditorWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="CanvasZone.xaml.cs">
|
||||
<DependentUpon>CanvasZone.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="GridZone.xaml.cs">
|
||||
<DependentUpon>GridZone.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="CanvasEditor.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="GridEditor.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="GridResizer.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="LayoutPreview.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Page Include="EditorOverlay.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="GridEditorWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WindowLayout.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="CanvasEditorWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="CanvasZone.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="GridZone.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MahApps.Metro">
|
||||
<Version>2.0.0-alpha0455</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="images\ChromeClose.png" />
|
||||
<Resource Include="images\Delete.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="images\Merge.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,35 @@
|
||||
<UserControl x:Class="FancyZonesEditor.GridEditor"
|
||||
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:local="clr-namespace:FancyZonesEditor"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<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>
|
||||
<Grid>
|
||||
<Canvas x:Name="Preview"/>
|
||||
<Canvas x:Name="AdornerLayer"/>
|
||||
<Canvas x:Name="MergePanel" Visibility="Collapsed" MouseUp="MergePanelMouseUp">
|
||||
|
||||
<StackPanel x:Name="MergeButtons" Background="Gray" Orientation="Horizontal">
|
||||
<Button Click="MergeClick" Margin="0" Height="36" Width="134">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Source="images/Merge.png" Margin="0,0,12,0" Height="16" HorizontalAlignment="Left" />
|
||||
<TextBlock Text="Merge zones"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Canvas>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,911 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// GridEditor is how you tweak an initial GridLayoutModel before saving
|
||||
/// </summary>
|
||||
public partial class GridEditor : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty ModelProperty = DependencyProperty.Register("Model", typeof(GridLayoutModel), typeof(GridEditor), new PropertyMetadata(null, OnGridDimensionsChanged));
|
||||
|
||||
public GridEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += GridEditor_Loaded;
|
||||
((App)Application.Current).ZoneSettings.PropertyChanged += ZoneSettings_PropertyChanged;
|
||||
}
|
||||
|
||||
private void GridEditor_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
GridLayoutModel model = (GridLayoutModel)DataContext;
|
||||
if (model != null)
|
||||
{
|
||||
int rows = model.Rows;
|
||||
int cols = model.Columns;
|
||||
_rowInfo = new RowColInfo[rows];
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
_rowInfo[row] = new RowColInfo(model.RowPercents[row]);
|
||||
}
|
||||
_colInfo = new RowColInfo[cols];
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
_colInfo[col] = new RowColInfo(model.ColumnPercents[col]);
|
||||
}
|
||||
|
||||
int maxIndex = 0;
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
maxIndex = Math.Max(maxIndex, model.CellChildMap[row, col]);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i <= maxIndex; i++)
|
||||
{
|
||||
AddZone();
|
||||
}
|
||||
}
|
||||
|
||||
Model = model;
|
||||
if (Model == null)
|
||||
{
|
||||
Model = new GridLayoutModel();
|
||||
DataContext = Model;
|
||||
}
|
||||
Model.PropertyChanged += OnGridDimensionsChanged;
|
||||
AddDragHandles();
|
||||
}
|
||||
|
||||
private void ZoneSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
Size actualSize = new Size(ActualWidth, ActualHeight);
|
||||
if (actualSize.Width > 0)
|
||||
{
|
||||
ArrangeGridRects(actualSize);
|
||||
}
|
||||
}
|
||||
|
||||
public GridLayoutModel Model
|
||||
{
|
||||
get { return (GridLayoutModel)GetValue(ModelProperty); }
|
||||
set { SetValue(ModelProperty, value); }
|
||||
}
|
||||
|
||||
public Panel PreviewPanel { get { return Preview; } }
|
||||
|
||||
private void OnFullSplit(object o, SplitEventArgs e)
|
||||
{
|
||||
UIElementCollection previewChildren = Preview.Children;
|
||||
UIElement splitee = (UIElement)o;
|
||||
|
||||
GridLayoutModel model = Model;
|
||||
int spliteeIndex = previewChildren.IndexOf(splitee);
|
||||
|
||||
int rows = model.Rows;
|
||||
int cols = model.Columns;
|
||||
_startRow = -1;
|
||||
_startCol = -1;
|
||||
|
||||
for (int row = rows - 1; row >= 0; row--)
|
||||
{
|
||||
for (int col = cols - 1; col >= 0; col--)
|
||||
{
|
||||
if (model.CellChildMap[row, col] == spliteeIndex)
|
||||
{
|
||||
RemoveDragHandles();
|
||||
_startRow = _endRow = row;
|
||||
_startCol = _endCol = col;
|
||||
ExtendRangeToHaveEvenCellEdges();
|
||||
|
||||
for (row = _startRow; row <= _endRow; row++)
|
||||
{
|
||||
for (col = _startCol; col <= _endCol; col++)
|
||||
{
|
||||
if ((row != _startRow) || (col != _startCol))
|
||||
{
|
||||
model.CellChildMap[row, col] = AddZone();
|
||||
}
|
||||
}
|
||||
}
|
||||
OnGridDimensionsChanged();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ExtendRangeToHaveEvenCellEdges()
|
||||
{
|
||||
// extend each edge of the [(_startCol, _startRow) - (_endCol, _endRow)] range based on merged cells until you have 4 straight edges with no "straddling cells"
|
||||
|
||||
GridLayoutModel model = Model;
|
||||
|
||||
while (_startRow > 0)
|
||||
{
|
||||
bool dirty = false;
|
||||
for (int col = _startCol; col <= _endCol; col++)
|
||||
{
|
||||
if (model.CellChildMap[_startRow - 1, col] == model.CellChildMap[_startRow, col])
|
||||
{
|
||||
_startRow--;
|
||||
dirty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dirty)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (_endRow < model.Rows - 1)
|
||||
{
|
||||
bool dirty = false;
|
||||
for (int col = _startCol; col <= _endCol; col++)
|
||||
{
|
||||
if (model.CellChildMap[_endRow + 1, col] == model.CellChildMap[_endRow, col])
|
||||
{
|
||||
_endRow++;
|
||||
dirty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dirty)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (_startCol > 0)
|
||||
{
|
||||
bool dirty = false;
|
||||
for (int row = _startRow; row <= _endRow; row++)
|
||||
{
|
||||
if (model.CellChildMap[row, _startCol - 1] == model.CellChildMap[row, _startCol])
|
||||
{
|
||||
_startCol--;
|
||||
dirty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dirty)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (_endCol < model.Columns - 1)
|
||||
{
|
||||
bool dirty = false;
|
||||
for (int row = _startRow; row <= _endRow; row++)
|
||||
{
|
||||
if (model.CellChildMap[row, _endCol + 1] == model.CellChildMap[row, _endCol])
|
||||
{
|
||||
_endCol++;
|
||||
dirty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dirty)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnSplit(object o, SplitEventArgs e)
|
||||
{
|
||||
UIElementCollection previewChildren = Preview.Children;
|
||||
GridZone splitee = (GridZone)o;
|
||||
|
||||
int spliteeIndex = previewChildren.IndexOf(splitee);
|
||||
GridLayoutModel model = Model;
|
||||
|
||||
int rows = model.Rows;
|
||||
int cols = model.Columns;
|
||||
int foundRow = -1;
|
||||
int foundCol = -1;
|
||||
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
if (model.CellChildMap[row, col] == spliteeIndex)
|
||||
{
|
||||
foundRow = row;
|
||||
foundCol = col;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundRow != -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int newChildIndex = AddZone();
|
||||
|
||||
double offset = e.Offset;
|
||||
|
||||
|
||||
if (e.Orientation == Orientation.Vertical)
|
||||
{
|
||||
if (splitee.VerticalSnapPoints != null)
|
||||
{
|
||||
offset += Canvas.GetLeft(splitee);
|
||||
int count = splitee.VerticalSnapPoints.Length;
|
||||
bool foundExistingSplit = false;
|
||||
|
||||
for (int i = 0; i <= count; i++)
|
||||
{
|
||||
if (foundExistingSplit)
|
||||
{
|
||||
int walkRow = foundRow;
|
||||
while ((walkRow < rows) && (model.CellChildMap[walkRow, foundCol + i] == spliteeIndex))
|
||||
{
|
||||
model.CellChildMap[walkRow++, foundCol + i] = newChildIndex;
|
||||
}
|
||||
}
|
||||
if (_colInfo[foundCol + i].End == offset)
|
||||
{
|
||||
foundExistingSplit = true;
|
||||
// use existing division
|
||||
}
|
||||
}
|
||||
|
||||
if (foundExistingSplit)
|
||||
{
|
||||
OnGridDimensionsChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
while (_colInfo[foundCol].End < offset)
|
||||
{
|
||||
foundCol++;
|
||||
}
|
||||
offset -= _colInfo[foundCol].Start;
|
||||
}
|
||||
|
||||
AddDragHandle(Orientation.Vertical, cols - 1);
|
||||
cols++;
|
||||
int[,] newCellChildMap = new int[rows, cols];
|
||||
int[] newColPercents = new int[cols];
|
||||
RowColInfo[] newColInfo = new RowColInfo[cols];
|
||||
|
||||
int sourceCol = 0;
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
if ((col > foundCol) && (model.CellChildMap[row, sourceCol] == spliteeIndex))
|
||||
{
|
||||
newCellChildMap[row, col] = newChildIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
newCellChildMap[row, col] = model.CellChildMap[row, sourceCol];
|
||||
}
|
||||
}
|
||||
if (col != foundCol)
|
||||
{
|
||||
sourceCol++;
|
||||
}
|
||||
}
|
||||
model.CellChildMap = newCellChildMap;
|
||||
|
||||
sourceCol = 0;
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
if (col == foundCol)
|
||||
{
|
||||
RowColInfo[] split = _colInfo[col].Split(offset);
|
||||
newColPercents[col] = split[0].Percent;
|
||||
newColInfo[col++] = split[0];
|
||||
newColPercents[col] = split[1].Percent;
|
||||
newColInfo[col] = split[1];
|
||||
sourceCol++;
|
||||
}
|
||||
else
|
||||
{
|
||||
newColPercents[col] = model.ColumnPercents[sourceCol];
|
||||
newColInfo[col] = _colInfo[sourceCol++];
|
||||
}
|
||||
}
|
||||
_colInfo = newColInfo;
|
||||
model.ColumnPercents = newColPercents;
|
||||
|
||||
model.Columns++;
|
||||
}
|
||||
else // Horizontal
|
||||
{
|
||||
|
||||
if (splitee.HorizontalSnapPoints != null)
|
||||
{
|
||||
offset += Canvas.GetTop(splitee);
|
||||
int count = splitee.HorizontalSnapPoints.Length;
|
||||
bool foundExistingSplit = false;
|
||||
|
||||
for (int i = 0; i <= count; i++)
|
||||
{
|
||||
if (foundExistingSplit)
|
||||
{
|
||||
int walkCol = foundCol;
|
||||
while ((walkCol < cols) && (model.CellChildMap[foundRow + i, walkCol] == spliteeIndex))
|
||||
{
|
||||
model.CellChildMap[foundRow + i, walkCol] = newChildIndex;
|
||||
}
|
||||
}
|
||||
if (_rowInfo[foundRow + i].End == offset)
|
||||
{
|
||||
foundExistingSplit = true;
|
||||
// use existing division
|
||||
}
|
||||
}
|
||||
|
||||
if (foundExistingSplit)
|
||||
{
|
||||
OnGridDimensionsChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
while (_rowInfo[foundRow].End < offset)
|
||||
{
|
||||
foundRow++;
|
||||
}
|
||||
offset -= _rowInfo[foundRow].Start;
|
||||
|
||||
}
|
||||
|
||||
AddDragHandle(Orientation.Horizontal, rows - 1);
|
||||
rows++;
|
||||
int[,] newCellChildMap = new int[rows, cols];
|
||||
int[] newRowPercents = new int[rows];
|
||||
RowColInfo[] newRowInfo = new RowColInfo[rows];
|
||||
|
||||
int sourceRow = 0;
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
if ((row > foundRow) && (model.CellChildMap[sourceRow, col] == spliteeIndex))
|
||||
{
|
||||
newCellChildMap[row, col] = newChildIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
newCellChildMap[row, col] = model.CellChildMap[sourceRow, col];
|
||||
}
|
||||
}
|
||||
if (row != foundRow)
|
||||
{
|
||||
sourceRow++;
|
||||
}
|
||||
}
|
||||
model.CellChildMap = newCellChildMap;
|
||||
|
||||
sourceRow = 0;
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
if (row == foundRow)
|
||||
{
|
||||
RowColInfo[] split = _rowInfo[row].Split(offset);
|
||||
newRowPercents[row] = split[0].Percent;
|
||||
newRowInfo[row++] = split[0];
|
||||
newRowPercents[row] = split[1].Percent;
|
||||
newRowInfo[row] = split[1];
|
||||
sourceRow++;
|
||||
}
|
||||
else
|
||||
{
|
||||
newRowPercents[row] = model.RowPercents[sourceRow];
|
||||
newRowInfo[row] = _rowInfo[sourceRow++];
|
||||
}
|
||||
}
|
||||
_rowInfo = newRowInfo;
|
||||
model.RowPercents = newRowPercents;
|
||||
|
||||
model.Rows++;
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveDragHandles()
|
||||
{
|
||||
AdornerLayer.Children.Clear();
|
||||
}
|
||||
|
||||
private void AddDragHandles()
|
||||
{
|
||||
if (AdornerLayer.Children.Count == 0)
|
||||
{
|
||||
int interiorRows = Model.Rows - 1;
|
||||
int interiorCols = Model.Columns - 1;
|
||||
|
||||
for (int row = 0; row < interiorRows; row++)
|
||||
{
|
||||
AddDragHandle(Orientation.Horizontal, row);
|
||||
}
|
||||
|
||||
for (int col = 0; col < interiorCols; col++)
|
||||
{
|
||||
AddDragHandle(Orientation.Vertical, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddDragHandle(Orientation orientation, int index)
|
||||
{
|
||||
GridResizer resizer = new GridResizer();
|
||||
resizer.Orientation = orientation;
|
||||
resizer.Index = index;
|
||||
resizer.Model = Model;
|
||||
resizer.DragDelta += Resizer_DragDelta;
|
||||
if (orientation == Orientation.Vertical)
|
||||
{
|
||||
index += (Model.Rows - 1);
|
||||
}
|
||||
AdornerLayer.Children.Insert(index, resizer);
|
||||
}
|
||||
|
||||
private void DeleteZone(int index)
|
||||
{
|
||||
IList<int> freeZones = Model.FreeZones;
|
||||
|
||||
if (freeZones.Contains(index))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
freeZones.Add(index);
|
||||
GridZone zone = (GridZone)Preview.Children[index];
|
||||
zone.Visibility = Visibility.Hidden;
|
||||
zone.MinHeight = 0;
|
||||
zone.MinWidth = 0;
|
||||
}
|
||||
|
||||
private int AddZone()
|
||||
{
|
||||
GridZone zone;
|
||||
if (Model != null)
|
||||
{
|
||||
IList<int> freeZones = Model.FreeZones;
|
||||
|
||||
// first check free list
|
||||
if (freeZones.Count > 0)
|
||||
{
|
||||
int freeIndex = freeZones[0];
|
||||
freeZones.RemoveAt(0);
|
||||
zone = (GridZone)Preview.Children[freeIndex];
|
||||
zone.Visibility = Visibility.Visible;
|
||||
return freeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
zone = new GridZone();
|
||||
zone.Split += OnSplit;
|
||||
zone.MergeDrag += OnMergeDrag;
|
||||
zone.MergeComplete += OnMergeComplete;
|
||||
zone.FullSplit += OnFullSplit;
|
||||
Preview.Children.Add(zone);
|
||||
return Preview.Children.Count - 1;
|
||||
}
|
||||
|
||||
private void OnGridDimensionsChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if ((e.PropertyName == "Rows") || (e.PropertyName == "Columns"))
|
||||
{
|
||||
OnGridDimensionsChanged();
|
||||
}
|
||||
}
|
||||
private static void OnGridDimensionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((GridEditor)d).OnGridDimensionsChanged();
|
||||
}
|
||||
private void OnGridDimensionsChanged()
|
||||
{
|
||||
GridLayoutModel model = Model;
|
||||
|
||||
Size actualSize = new Size(ActualWidth, ActualHeight);
|
||||
if (actualSize.Width > 0)
|
||||
{
|
||||
ArrangeGridRects(actualSize);
|
||||
}
|
||||
}
|
||||
|
||||
private void ArrangeGridRects(Size arrangeSize)
|
||||
{
|
||||
GridLayoutModel model = Model;
|
||||
if (model == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Settings settings = ((App)(Application.Current)).ZoneSettings;
|
||||
int spacing = settings.Spacing;
|
||||
int gutter = settings.Spacing;
|
||||
|
||||
int cols = model.Columns;
|
||||
int rows = model.Rows;
|
||||
|
||||
double totalWidth = arrangeSize.Width - (gutter * 2) - (spacing * (cols - 1));
|
||||
double totalHeight = arrangeSize.Height - (gutter * 2) - (spacing * (rows - 1));
|
||||
|
||||
double top = gutter;
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
double cellHeight = _rowInfo[row].SetExtent(top, totalHeight);
|
||||
top += cellHeight + spacing;
|
||||
}
|
||||
|
||||
double left = gutter;
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
double cellWidth = _colInfo[col].SetExtent(left, totalWidth);
|
||||
left += cellWidth + spacing;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
int i = model.CellChildMap[row, col];
|
||||
if (((row == 0) || (model.CellChildMap[row - 1, col] != i)) &&
|
||||
((col == 0) || (model.CellChildMap[row, col - 1] != i)))
|
||||
{
|
||||
// this is not a continuation of a span
|
||||
GridZone zone = (GridZone)Preview.Children[i];
|
||||
left = _colInfo[col].Start;
|
||||
top = _rowInfo[row].Start;
|
||||
Canvas.SetLeft(zone, left);
|
||||
Canvas.SetTop(zone, top);
|
||||
|
||||
int maxRow = row;
|
||||
while (((maxRow + 1) < rows) && (model.CellChildMap[maxRow + 1, col] == i))
|
||||
{
|
||||
maxRow++;
|
||||
}
|
||||
zone.HorizontalSnapPoints = null;
|
||||
if (maxRow > row)
|
||||
{
|
||||
zone.HorizontalSnapPoints = new double[maxRow - row];
|
||||
int pointsIndex = 0;
|
||||
for (int walk = row; walk < maxRow; walk++)
|
||||
{
|
||||
zone.HorizontalSnapPoints[pointsIndex++] = _rowInfo[walk].End + spacing / 2 - top;
|
||||
}
|
||||
}
|
||||
|
||||
int maxCol = col;
|
||||
while (((maxCol + 1) < cols) && (model.CellChildMap[row, maxCol + 1] == i))
|
||||
{
|
||||
maxCol++;
|
||||
}
|
||||
|
||||
zone.VerticalSnapPoints = null;
|
||||
if (maxCol > col)
|
||||
{
|
||||
zone.VerticalSnapPoints = new double[maxCol - col];
|
||||
int pointsIndex = 0;
|
||||
for (int walk = col; walk < maxCol; walk++)
|
||||
{
|
||||
zone.VerticalSnapPoints[pointsIndex++] = _colInfo[walk].End + spacing / 2 - left;
|
||||
}
|
||||
}
|
||||
|
||||
zone.MinWidth = _colInfo[maxCol].End - left;
|
||||
zone.MinHeight = _rowInfo[maxRow].End - top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddDragHandles();
|
||||
int childIndex = 0;
|
||||
UIElementCollection adornerChildren = AdornerLayer.Children;
|
||||
for (int row = 0; row < rows - 1; row++)
|
||||
{
|
||||
GridResizer resizer = (GridResizer)adornerChildren[childIndex++];
|
||||
int startCol = -1;
|
||||
int endCol = cols - 1;
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
if ((startCol == -1) && (model.CellChildMap[row, col] != model.CellChildMap[row + 1, col]))
|
||||
{
|
||||
startCol = col;
|
||||
}
|
||||
else if ((startCol != -1) && (model.CellChildMap[row, col] == model.CellChildMap[row + 1, col]))
|
||||
{
|
||||
endCol = col - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (startCol != -1)
|
||||
{
|
||||
Canvas.SetTop(resizer, _rowInfo[row].End + (spacing / 2) - 24); // hard coding this as (resizer.ActualHeight / 2) will still evaluate to 0 here ... a layout hasn't yet happened
|
||||
Canvas.SetLeft(resizer, (_colInfo[endCol].End + _colInfo[startCol].Start) / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
resizer.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
for (int col = 0; col < cols - 1; col++)
|
||||
{
|
||||
GridResizer resizer = (GridResizer)adornerChildren[childIndex++];
|
||||
int startRow = -1;
|
||||
int endRow = rows - 1;;
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
if ((startRow == -1) && (model.CellChildMap[row, col] != model.CellChildMap[row, col + 1]))
|
||||
{
|
||||
startRow = row;
|
||||
}
|
||||
else if ((startRow != -1) && (model.CellChildMap[row, col] == model.CellChildMap[row, col + 1]))
|
||||
{
|
||||
endRow = row - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (startRow != -1)
|
||||
{
|
||||
Canvas.SetLeft(resizer, _colInfo[col].End + (spacing / 2) - 24); // hard coding this as (resizer.ActualWidth / 2) will still evaluate to 0 here ... a layout hasn't yet happened
|
||||
Canvas.SetTop(resizer, (_rowInfo[endRow].End + _rowInfo[startRow].Start) / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
resizer.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Resizer_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
||||
{
|
||||
GridResizer resizer = (GridResizer)sender;
|
||||
int[] percents;
|
||||
RowColInfo[] info;
|
||||
int index = resizer.Index;
|
||||
double delta;
|
||||
|
||||
if (resizer.Orientation == Orientation.Vertical)
|
||||
{
|
||||
percents = Model.ColumnPercents;
|
||||
info = _colInfo;
|
||||
delta = e.HorizontalChange;
|
||||
}
|
||||
else
|
||||
{
|
||||
percents = Model.RowPercents;
|
||||
info = _rowInfo;
|
||||
delta = e.VerticalChange;
|
||||
}
|
||||
|
||||
double currentExtent = info[index].Extent;
|
||||
double newExtent = currentExtent + delta;
|
||||
int currentPercent = info[index].Percent;
|
||||
int totalPercent = currentPercent + info[index + 1].Percent;
|
||||
|
||||
int newPercent = (int)(currentPercent * newExtent / currentExtent);
|
||||
|
||||
if ((newPercent > 0) && (newPercent < totalPercent))
|
||||
{
|
||||
percents[index] = info[index].Percent = newPercent;
|
||||
percents[index + 1] = info[index + 1].Percent = totalPercent - newPercent;
|
||||
|
||||
Size actualSize = new Size(ActualWidth, ActualHeight);
|
||||
ArrangeGridRects(actualSize);
|
||||
}
|
||||
}
|
||||
|
||||
private Point _startDragPos = new Point(-1, -1);
|
||||
|
||||
private void OnMergeComplete(object o, MouseButtonEventArgs e)
|
||||
{
|
||||
Point mousePoint = e.GetPosition(Preview);
|
||||
_startDragPos = new Point(-1, -1);
|
||||
|
||||
int mergedIndex = Model.CellChildMap[_startRow, _startCol];
|
||||
|
||||
for (int row = _startRow; row <= _endRow; row++)
|
||||
{
|
||||
for (int col = _startCol; col <= _endCol; col++)
|
||||
{
|
||||
if (Model.CellChildMap[row, col] != mergedIndex)
|
||||
{
|
||||
// selection is more than one cell, merge is valid
|
||||
MergePanel.Visibility = Visibility.Visible;
|
||||
Canvas.SetTop(MergeButtons, mousePoint.Y);
|
||||
Canvas.SetLeft(MergeButtons, mousePoint.X);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// merge is only one zone. cancel merge;
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
private void OnMergeDrag(object o, MouseEventArgs e)
|
||||
{
|
||||
if (_startDragPos.X == -1)
|
||||
{
|
||||
_startDragPos = e.GetPosition(Preview);
|
||||
}
|
||||
|
||||
GridLayoutModel model = Model;
|
||||
|
||||
if (_startDragPos.X != -1)
|
||||
{
|
||||
Point dragPos = e.GetPosition(Preview);
|
||||
|
||||
_startRow = -1;
|
||||
_endRow = -1;
|
||||
_startCol = -1;
|
||||
_endCol = -1;
|
||||
|
||||
int rows = model.Rows;
|
||||
int cols = model.Columns;
|
||||
|
||||
double minX, maxX;
|
||||
if (dragPos.X < _startDragPos.X)
|
||||
{
|
||||
minX = dragPos.X;
|
||||
maxX = _startDragPos.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
minX = _startDragPos.X;
|
||||
maxX = dragPos.X;
|
||||
}
|
||||
|
||||
double minY, maxY;
|
||||
if (dragPos.Y < _startDragPos.Y)
|
||||
{
|
||||
minY = dragPos.Y;
|
||||
maxY = _startDragPos.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
minY = _startDragPos.Y;
|
||||
maxY = dragPos.Y;
|
||||
}
|
||||
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
if (_startRow == -1)
|
||||
{
|
||||
if (_rowInfo[row].End > minY)
|
||||
{
|
||||
_startRow = row;
|
||||
}
|
||||
}
|
||||
else if (_rowInfo[row].Start > maxY)
|
||||
{
|
||||
_endRow = row - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((_startRow >= 0) && (_endRow == -1))
|
||||
{
|
||||
_endRow = rows - 1;
|
||||
}
|
||||
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
if (_startCol == -1)
|
||||
{
|
||||
if (_colInfo[col].End > minX)
|
||||
{
|
||||
_startCol = col;
|
||||
}
|
||||
}
|
||||
else if (_colInfo[col].Start > maxX)
|
||||
{
|
||||
_endCol = col - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((_startCol >= 0) && (_endCol == -1))
|
||||
{
|
||||
_endCol = cols - 1;
|
||||
}
|
||||
|
||||
ExtendRangeToHaveEvenCellEdges();
|
||||
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
((GridZone)Preview.Children[model.CellChildMap[row, col]]).IsSelected = (row >= _startRow) && (row <= _endRow) && (col >= _startCol) && (col <= _endCol);
|
||||
}
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
base.OnPreviewMouseMove(e);
|
||||
}
|
||||
|
||||
private void ClearSelection()
|
||||
{
|
||||
foreach (UIElement zone in Preview.Children)
|
||||
{
|
||||
((GridZone) zone).IsSelected = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void MergeClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
GridLayoutModel model = Model;
|
||||
|
||||
MergePanel.Visibility = Visibility.Collapsed;
|
||||
int mergedIndex = model.CellChildMap[_startRow, _startCol];
|
||||
|
||||
for (int row = _startRow; row <= _endRow; row++)
|
||||
{
|
||||
for (int col = _startCol; col <= _endCol; col++)
|
||||
{
|
||||
int childIndex = model.CellChildMap[row, col];
|
||||
if (childIndex != mergedIndex)
|
||||
{
|
||||
model.CellChildMap[row, col] = mergedIndex;
|
||||
DeleteZone(childIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
OnGridDimensionsChanged();
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
private void CancelClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MergePanel.Visibility = Visibility.Collapsed;
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
private void MergePanelMouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
CancelClick(null, null);
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size arrangeBounds)
|
||||
{
|
||||
Size returnSize = base.ArrangeOverride(arrangeBounds);
|
||||
ArrangeGridRects(arrangeBounds);
|
||||
|
||||
return returnSize;
|
||||
}
|
||||
|
||||
Point _mouseDownPos = new Point(-1, -1);
|
||||
private RowColInfo[] _rowInfo;
|
||||
private RowColInfo[] _colInfo;
|
||||
|
||||
private int _startRow = -1;
|
||||
private int _endRow = -1;
|
||||
private int _startCol = -1;
|
||||
private int _endCol = -1;
|
||||
|
||||
private const int c_multiplier = 10000;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
<local:EditorWindow x:Class="FancyZonesEditor.GridEditorWindow"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
Title=""
|
||||
Width="528"
|
||||
SizeToContent="Height"
|
||||
Background="White"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Closed="OnClosed">
|
||||
|
||||
<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,20,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="secondaryButton" 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="Padding" Value="0,5,0,5"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="#F2F2F2"/>
|
||||
<Setter Property="Margin" Value="16,10,0,0" />
|
||||
<Setter Property="Width" Value="239"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<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="#BCBCBD"/>
|
||||
</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="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="#cccccc"/>
|
||||
<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>
|
||||
<TextBlock Name="windowEditorDialogTitle" Text="Custom table layout creator" Style="{StaticResource titleText}" />
|
||||
|
||||
<TextBlock Text="Note: Hold down Shift Key to change orientation of splitter" Style="{StaticResource textLabel}" />
|
||||
<TextBlock Text="Name" Style="{StaticResource textLabel}" />
|
||||
<TextBox Text="{Binding Name}" Width="494" 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}"/>
|
||||
</StackPanel>
|
||||
-->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,12,0,16">
|
||||
<Button Content="Cancel" Style="{StaticResource secondaryButton}" Click="OnCancel" />
|
||||
<Button Content="Save and apply" Style="{StaticResource primaryButton}" Click="OnSaveApplyTemplate" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</local:EditorWindow>
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using FancyZonesEditor.Models;
|
||||
using MahApps.Metro.Controls;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for Window2.xaml
|
||||
/// </summary>
|
||||
public partial class GridEditorWindow : EditorWindow
|
||||
{
|
||||
public GridEditorWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Thumb x:Class="FancyZonesEditor.GridResizer"
|
||||
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:local="clr-namespace:FancyZonesEditor"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300" d:DesignWidth="300">
|
||||
<Thumb.Template>
|
||||
<ControlTemplate>
|
||||
<StackPanel x:Name="Body" Grid.Column="0" Width="48" Height="48">
|
||||
<Ellipse Height="48" Width="48" Fill="#0078D7" />
|
||||
<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>
|
||||
</ControlTemplate>
|
||||
</Thumb.Template>
|
||||
</Thumb>
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using FancyZonesEditor.Models;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for GridResizer.xaml
|
||||
/// </summary>
|
||||
public partial class GridResizer : Thumb
|
||||
{
|
||||
public GridResizer()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public Orientation Orientation
|
||||
{
|
||||
get
|
||||
{
|
||||
return _orientation;
|
||||
}
|
||||
set
|
||||
{
|
||||
_orientation = value;
|
||||
ApplyTemplate();
|
||||
StackPanel body = (StackPanel)Template.FindName("Body", this);
|
||||
if (value == Orientation.Vertical)
|
||||
{
|
||||
body.RenderTransform = null;
|
||||
body.Cursor = Cursors.SizeWE;
|
||||
}
|
||||
else
|
||||
{
|
||||
body.RenderTransform = c_rotateTransform;
|
||||
body.Cursor = Cursors.SizeNS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static RotateTransform c_rotateTransform = new RotateTransform(90, 24, 24);
|
||||
|
||||
public int Index;
|
||||
public LayoutModel Model;
|
||||
|
||||
private Orientation _orientation;
|
||||
|
||||
}
|
||||
}
|
||||
15
src/modules/fancyzones/editor/FancyZonesEditor/GridZone.xaml
Normal file
15
src/modules/fancyzones/editor/FancyZonesEditor/GridZone.xaml
Normal file
@@ -0,0 +1,15 @@
|
||||
<UserControl x:Class="FancyZonesEditor.GridZone"
|
||||
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:local="clr-namespace:FancyZonesEditor"
|
||||
mc:Ignorable="d"
|
||||
Background="LightGray"
|
||||
Opacity="0.5"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid x:Name="Frame" Visibility="Collapsed">
|
||||
<Canvas x:Name="Body" />
|
||||
<!--<TextBlock Margin="2" Text="Shift Key switches direction Ctrl Key repeats"/>-->
|
||||
</Grid>
|
||||
</UserControl>
|
||||
309
src/modules/fancyzones/editor/FancyZonesEditor/GridZone.xaml.cs
Normal file
309
src/modules/fancyzones/editor/FancyZonesEditor/GridZone.xaml.cs
Normal file
@@ -0,0 +1,309 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Once you've "Committ"ed the starter grid, then the Zones within the grid come to life for you to be able to further subdivide them
|
||||
/// using splitters
|
||||
/// </summary>
|
||||
|
||||
public partial class GridZone : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(GridZone), new PropertyMetadata(false, OnSelectionChanged));
|
||||
|
||||
private static void OnSelectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((GridZone)d).OnSelectionChanged();
|
||||
}
|
||||
private void OnSelectionChanged()
|
||||
{
|
||||
Background = IsSelected ? Brushes.SteelBlue : Brushes.LightGray;
|
||||
}
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get { return (bool)GetValue(IsSelectedProperty); }
|
||||
set { SetValue(IsSelectedProperty, value); }
|
||||
}
|
||||
|
||||
|
||||
public double[] VerticalSnapPoints;
|
||||
public double[] HorizontalSnapPoints;
|
||||
|
||||
|
||||
|
||||
public GridZone()
|
||||
{
|
||||
InitializeComponent();
|
||||
OnSelectionChanged();
|
||||
_splitter = new Rectangle();
|
||||
_splitter.Fill = Brushes.DarkGray;
|
||||
Body.Children.Add(_splitter);
|
||||
|
||||
((App) Application.Current).ZoneSettings.PropertyChanged += ZoneSettings_PropertyChanged;
|
||||
}
|
||||
|
||||
private void ZoneSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "IsShiftKeyPressed")
|
||||
{
|
||||
_switchOrientation = ((App)Application.Current).ZoneSettings.IsShiftKeyPressed;
|
||||
if (_lastPos.X != -1)
|
||||
{
|
||||
UpdateSplitter();
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override Size ArrangeOverride(Size size)
|
||||
{
|
||||
_splitOrientation = (size.Width > size.Height) ? Orientation.Vertical : Orientation.Horizontal;
|
||||
return base.ArrangeOverride(size);
|
||||
}
|
||||
|
||||
private bool IsVerticalSplit
|
||||
{
|
||||
get
|
||||
{
|
||||
bool isVertical = _splitOrientation == Orientation.Vertical;
|
||||
if (_switchOrientation)
|
||||
{
|
||||
isVertical = !isVertical;
|
||||
}
|
||||
return isVertical;
|
||||
}
|
||||
}
|
||||
|
||||
private int SplitterThickness { get { return Math.Max(((App)Application.Current).ZoneSettings.Spacing, 5); } }
|
||||
|
||||
private void UpdateSplitter()
|
||||
{
|
||||
int thickness = SplitterThickness;
|
||||
|
||||
if (IsVerticalSplit)
|
||||
{
|
||||
double bodyWidth = Body.ActualWidth;
|
||||
double pos = _lastPos.X - thickness/2;
|
||||
if (pos < 0)
|
||||
{
|
||||
pos = 0;
|
||||
}
|
||||
else if (pos > (bodyWidth - thickness))
|
||||
{
|
||||
pos = bodyWidth - thickness;
|
||||
}
|
||||
|
||||
Canvas.SetLeft(_splitter, pos);
|
||||
Canvas.SetTop(_splitter, 0);
|
||||
_splitter.MinWidth = thickness;
|
||||
_splitter.MinHeight = Body.ActualHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
double bodyHeight = Body.ActualHeight;
|
||||
double pos = _lastPos.Y - thickness / 2;
|
||||
if (pos < 0)
|
||||
{
|
||||
pos = 0;
|
||||
}
|
||||
else if (pos > (bodyHeight - thickness))
|
||||
{
|
||||
pos = bodyHeight - thickness;
|
||||
}
|
||||
Canvas.SetLeft(_splitter, 0);
|
||||
Canvas.SetTop(_splitter, pos);
|
||||
_splitter.MinWidth = Body.ActualWidth;
|
||||
_splitter.MinHeight = thickness;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseEnter(MouseEventArgs e)
|
||||
{
|
||||
Frame.Visibility = Visibility.Visible;
|
||||
base.OnMouseEnter(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(MouseEventArgs e)
|
||||
{
|
||||
Frame.Visibility = Visibility.Collapsed;
|
||||
base.OnMouseLeave(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseButtonEventArgs e)
|
||||
{
|
||||
_mouseDownPos = _lastPos;
|
||||
base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
if (_inMergeDrag)
|
||||
{
|
||||
DoMergeDrag(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastPos = e.GetPosition(Body);
|
||||
|
||||
if (IsVerticalSplit)
|
||||
{
|
||||
if (VerticalSnapPoints != null)
|
||||
{
|
||||
int thickness = SplitterThickness;
|
||||
foreach (double snapPoint in VerticalSnapPoints)
|
||||
{
|
||||
if (Math.Abs(_lastPos.X - snapPoint) <= (thickness * 2))
|
||||
{
|
||||
_lastPos.X = snapPoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // horizontal split
|
||||
{
|
||||
if (HorizontalSnapPoints != null)
|
||||
{
|
||||
int thickness = SplitterThickness;
|
||||
foreach (double snapPoint in HorizontalSnapPoints)
|
||||
{
|
||||
if (Math.Abs(_lastPos.Y - snapPoint) <= (thickness * 2))
|
||||
{
|
||||
_lastPos.Y = snapPoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_mouseDownPos.X == -1)
|
||||
{
|
||||
UpdateSplitter();
|
||||
}
|
||||
else
|
||||
{
|
||||
double threshold = SplitterThickness / 2;
|
||||
if ((Math.Abs(_mouseDownPos.X - _lastPos.X) > threshold) || (Math.Abs(_mouseDownPos.Y - _lastPos.Y) > threshold))
|
||||
{
|
||||
// switch to merge (which is handled by parent GridEditor)
|
||||
_inMergeDrag = true;
|
||||
Mouse.Capture(this, CaptureMode.Element);
|
||||
DoMergeDrag(e);
|
||||
_splitter.Visibility = Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseButtonEventArgs e)
|
||||
{
|
||||
if (_inMergeDrag)
|
||||
{
|
||||
Mouse.Capture(this, CaptureMode.None);
|
||||
DoMergeComplete(e);
|
||||
_inMergeDrag = false;
|
||||
_splitter.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
int thickness = SplitterThickness;
|
||||
|
||||
double delta = IsVerticalSplit ? _mouseDownPos.X - _lastPos.X : _mouseDownPos.Y - _lastPos.Y;
|
||||
if (Math.Abs(delta) <= thickness / 2)
|
||||
{
|
||||
if (IsVerticalSplit)
|
||||
{
|
||||
DoSplit(Orientation.Vertical, _lastPos.X - (thickness / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
DoSplit(Orientation.Horizontal, _lastPos.Y - (thickness / 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
_mouseDownPos = new Point(-1, -1);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
public event SplitEventHandler Split;
|
||||
public event SplitEventHandler FullSplit;
|
||||
public event MouseEventHandler MergeDrag;
|
||||
public event MouseButtonEventHandler MergeComplete;
|
||||
|
||||
|
||||
private Rectangle _splitter;
|
||||
private bool _switchOrientation = false;
|
||||
private Point _lastPos = new Point(-1,-1);
|
||||
private Point _mouseDownPos = new Point(-1,-1);
|
||||
private bool _inMergeDrag = false;
|
||||
private Orientation _splitOrientation;
|
||||
|
||||
private void DoMergeDrag(MouseEventArgs e)
|
||||
{
|
||||
if (MergeDrag != null)
|
||||
{
|
||||
MergeDrag(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void DoMergeComplete(MouseButtonEventArgs e)
|
||||
{
|
||||
if (MergeComplete != null)
|
||||
{
|
||||
MergeComplete(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void DoSplit(Orientation orientation, double offset)
|
||||
{
|
||||
if (Split != null)
|
||||
{
|
||||
Split(this, new SplitEventArgs(orientation, offset));
|
||||
}
|
||||
}
|
||||
|
||||
private void FullSplit_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DoFullSplit();
|
||||
}
|
||||
|
||||
private void DoFullSplit()
|
||||
{
|
||||
if (FullSplit != null)
|
||||
{
|
||||
FullSplit(this, new SplitEventArgs());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SplitEventArgs : EventArgs
|
||||
{
|
||||
public SplitEventArgs() { }
|
||||
public SplitEventArgs(Orientation orientation, double offset)
|
||||
{
|
||||
_orientation = orientation;
|
||||
_offset = offset;
|
||||
}
|
||||
|
||||
public Orientation Orientation { get { return _orientation; } }
|
||||
public double Offset { get { return _offset; } }
|
||||
|
||||
private Orientation _orientation;
|
||||
private double _offset;
|
||||
}
|
||||
|
||||
public delegate void SplitEventHandler(object sender, SplitEventArgs args);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<UserControl x:Class="FancyZonesEditor.LayoutPreview"
|
||||
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:local="clr-namespace:FancyZonesEditor"
|
||||
mc:Ignorable="d"
|
||||
Loaded="OnLoaded"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid x:Name="Body">
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,192 @@
|
||||
using FancyZonesEditor.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for LayoutPreview.xaml
|
||||
/// </summary>
|
||||
public partial class LayoutPreview : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty IsActualSizeProperty = DependencyProperty.Register("IsActualSize", typeof(bool), typeof(LayoutPreview), new PropertyMetadata(false));
|
||||
public LayoutPreview()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContextChanged += LayoutPreview_DataContextChanged;
|
||||
((App)Application.Current).ZoneSettings.PropertyChanged += ZoneSettings_PropertyChanged;
|
||||
}
|
||||
|
||||
private void LayoutPreview_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
_model = (LayoutModel)DataContext;
|
||||
RenderPreview();
|
||||
}
|
||||
|
||||
public bool IsActualSize
|
||||
{
|
||||
get { return (bool)GetValue(IsActualSizeProperty); }
|
||||
set { SetValue(IsActualSizeProperty, value); }
|
||||
}
|
||||
|
||||
private void ZoneSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "ZoneCount")
|
||||
{
|
||||
RenderPreview();
|
||||
}
|
||||
else if ((e.PropertyName == "ShowSpacing") || (e.PropertyName == "Spacing"))
|
||||
{
|
||||
if (IsActualSize)
|
||||
{
|
||||
Settings settings = ((App)Application.Current).ZoneSettings;
|
||||
Body.Margin = new Thickness(settings.ShowSpacing ? settings.Spacing / 2 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Body.Margin = new Thickness(0);
|
||||
}
|
||||
if (_model is GridLayoutModel)
|
||||
{
|
||||
RenderPreview();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Panel PreviewPanel { get { return Body; } }
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_model = (LayoutModel)DataContext;
|
||||
|
||||
RenderPreview();
|
||||
}
|
||||
|
||||
private void RenderPreview()
|
||||
{
|
||||
if (_model == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Body.Children.Clear();
|
||||
|
||||
GridLayoutModel gridModel = _model as GridLayoutModel;
|
||||
if (gridModel != null)
|
||||
{
|
||||
RenderGridPreview(gridModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
CanvasLayoutModel canvasModel = _model as CanvasLayoutModel;
|
||||
if (canvasModel != null)
|
||||
{
|
||||
RenderCanvasPreview(canvasModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderGridPreview(GridLayoutModel grid)
|
||||
{
|
||||
Body.RowDefinitions.Clear();
|
||||
foreach (int percent in grid.RowPercents)
|
||||
{
|
||||
RowDefinition def = new RowDefinition();
|
||||
def.Height = new GridLength(percent, GridUnitType.Star);
|
||||
Body.RowDefinitions.Add(def);
|
||||
}
|
||||
|
||||
Body.ColumnDefinitions.Clear();
|
||||
foreach (int percent in grid.ColumnPercents)
|
||||
{
|
||||
ColumnDefinition def = new ColumnDefinition();
|
||||
def.Width = new GridLength(percent, GridUnitType.Star);
|
||||
Body.ColumnDefinitions.Add(def);
|
||||
}
|
||||
|
||||
Settings settings = ((App) Application.Current).ZoneSettings;
|
||||
int divisor = IsActualSize ? 2 : 20;
|
||||
Thickness margin = new Thickness(settings.ShowSpacing ? settings.Spacing / divisor : 0);
|
||||
|
||||
List<int> visited = new List<int>();
|
||||
|
||||
for (int row = 0; row < grid.Rows; row++)
|
||||
{
|
||||
for (int col = 0; col < grid.Columns; col++)
|
||||
{
|
||||
int childIndex = grid.CellChildMap[row,col];
|
||||
if (!visited.Contains(childIndex))
|
||||
{
|
||||
visited.Add(childIndex);
|
||||
Rectangle rect = new Rectangle();
|
||||
Grid.SetRow(rect, row);
|
||||
Grid.SetColumn(rect, col);
|
||||
int span = 1;
|
||||
int walk = row + 1;
|
||||
while ((walk < grid.Rows) && grid.CellChildMap[walk,col] == childIndex)
|
||||
{
|
||||
span++;
|
||||
walk++;
|
||||
}
|
||||
Grid.SetRowSpan(rect, span);
|
||||
|
||||
span = 1;
|
||||
walk = col + 1;
|
||||
while ((walk < grid.Columns) && grid.CellChildMap[row, walk] == childIndex)
|
||||
{
|
||||
span++;
|
||||
walk++;
|
||||
}
|
||||
Grid.SetColumnSpan(rect, span);
|
||||
|
||||
rect.Margin = margin;
|
||||
rect.StrokeThickness = 1;
|
||||
rect.Stroke = Brushes.DarkGray;
|
||||
rect.Fill = Brushes.LightGray;
|
||||
Body.Children.Add(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderCanvasPreview(CanvasLayoutModel canvas)
|
||||
{
|
||||
Body.RowDefinitions.Clear();
|
||||
Body.ColumnDefinitions.Clear();
|
||||
|
||||
Viewbox viewbox = new Viewbox();
|
||||
viewbox.Stretch = Stretch.Uniform;
|
||||
Body.Children.Add(viewbox);
|
||||
Canvas frame = new Canvas();
|
||||
viewbox.Child = frame;
|
||||
frame.Width = canvas.ReferenceWidth;
|
||||
frame.Height = canvas.ReferenceHeight;
|
||||
foreach (Int32Rect zone in canvas.Zones)
|
||||
{
|
||||
Rectangle rect = new Rectangle();
|
||||
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;
|
||||
frame.Children.Add(rect);
|
||||
}
|
||||
}
|
||||
|
||||
private LayoutModel _model;
|
||||
}
|
||||
}
|
||||
277
src/modules/fancyzones/editor/FancyZonesEditor/MainWindow.xaml
Normal file
277
src/modules/fancyzones/editor/FancyZonesEditor/MainWindow.xaml
Normal file
@@ -0,0 +1,277 @@
|
||||
<Controls:MetroWindow x:Class="FancyZonesEditor.MainWindow"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
Title="" Width="810"
|
||||
SizeToContent="Height"
|
||||
Background="White"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Loaded="OnLoaded"
|
||||
Closed="OnClosed">
|
||||
<Window.Resources>
|
||||
<local:BooleanToBrushConverter x:Key="BooleanToBrushConverter" />
|
||||
<local:ModelToVisibilityConverter x:Key="ModelToVisibilityConverter" />
|
||||
|
||||
<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,20,0,0" />
|
||||
</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="40,10,0,0" />
|
||||
<Setter Property="TextAlignment" Value="Left" />
|
||||
</Style>
|
||||
<Style x:Key="settingCheckBoxText" TargetType="CheckBox">
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Margin" Value="5,10,0,0" />
|
||||
</Style>
|
||||
<Style x:Key="templateTitleText" 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="TextAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
<Style x:Key="secondaryButton" 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="Padding" Value="0,5,0,5"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="#F2F2F2"/>
|
||||
<Setter Property="Margin" Value="16,0,0,0" />
|
||||
<Setter Property="Width" Value="378"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<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="#BCBCBD"/>
|
||||
</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,16,0" />
|
||||
<Setter Property="Width" Value="377"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<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="newLayoutButton" 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="148"/>
|
||||
</Style>
|
||||
<Style x:Key="textBox" TargetType="TextBox">
|
||||
<Setter Property="BorderBrush" Value="#cccccc"/>
|
||||
<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="16,6,0,0"/>
|
||||
<Setter Property="Padding" Value="5,5,5,5"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="templateBackground" TargetType="Border">
|
||||
<Setter Property="Background" Value="#F2F2F2"/>
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="BorderThickness" Value="2"/>
|
||||
</Style>
|
||||
|
||||
<ControlTemplate x:Key="myTabs">
|
||||
<Grid Width="404">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="40"/>
|
||||
<RowDefinition Height="2"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Name="myTabText" Text="{TemplateBinding TabItem.Header}" Style="{StaticResource tabText}" />
|
||||
<Rectangle Grid.Row="1" x:Name="myTabLine" Fill="#F2F2F2" Height="1"/>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="TabItem.IsSelected" Value="True">
|
||||
<Setter TargetName="myTabText" Property="Foreground" Value="#2A79D7"/>
|
||||
<Setter TargetName="myTabLine" Property="Fill" Value="#2A79D7" />
|
||||
<Setter TargetName="myTabLine" Property="Height" Value="2"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Window.Resources>
|
||||
|
||||
<StackPanel>
|
||||
|
||||
<TextBlock Name="dialog_Title" Text="Choose your layout" Style="{StaticResource titleText}" />
|
||||
|
||||
|
||||
<TabControl BorderThickness="0" x:Name="TemplateTab">
|
||||
<TabItem Header="Templates" Template="{StaticResource myTabs}">
|
||||
<StackPanel>
|
||||
<StackPanel Margin="0,15,0,8" Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button x:Name="decrementZones" Width="40" Height="40" Content="-" Style="{StaticResource spinnerButton}" Click="DecrementZones_Click"/>
|
||||
<TextBlock x:Name="zoneCount" Text="{Binding ZoneCount}" Style="{StaticResource zoneCount}"/>
|
||||
<Button x:Name="incrementZones" Width="40" Height="40" Content="+" Style="{StaticResource spinnerButton}" Click="IncrementZones_Click"/>
|
||||
</StackPanel>
|
||||
<ItemsControl ItemsSource="{Binding DefaultModels}" Margin="8,0,0,0">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" ItemWidth="262" ItemHeight="262" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Margin="8"
|
||||
BorderBrush="{Binding Path=IsSelected, Converter={StaticResource BooleanToBrushConverter}}"
|
||||
Style="{StaticResource templateBackground}"
|
||||
MouseDown="LayoutItem_Click">
|
||||
<DockPanel Margin="0,20,0,0"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
LastChildFill="True">
|
||||
<TextBlock Padding="8,0,8,0"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
DockPanel.Dock="Top"
|
||||
Text="{Binding Name}"
|
||||
Style="{StaticResource templateTitleText}" />
|
||||
<local:LayoutPreview Margin="16" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="10,4,0,8">
|
||||
<CheckBox x:Name="spaceAroundSetting" Content="Show space around zones" Style="{StaticResource settingCheckBoxText}" IsChecked="{Binding ShowSpacing}"/>
|
||||
<TextBlock Text="Space around zones" Style="{StaticResource settingText}"/>
|
||||
<TextBox x:Name="paddingValue" Text="{Binding Path=Spacing,Mode=TwoWay}" Style="{StaticResource textBox}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
|
||||
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,12,0,16">
|
||||
<Button x:Name="EditTemplateBUtton" Padding="8" Content="Edit selected layout" Style="{StaticResource secondaryButton}" Click="EditLayout_Click"/>
|
||||
<Button x:Name="ApplyTemplateButton" Padding="8" Content="Apply" Style="{StaticResource primaryButton}" Click="Apply_Click"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TabItem>
|
||||
|
||||
|
||||
<TabItem Header="Custom" Template="{StaticResource myTabs}">
|
||||
<StackPanel>
|
||||
<ItemsControl ItemsSource="{Binding CustomModels}" Margin="8,8,0,0">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" ItemWidth="262" ItemHeight="262" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Margin="8"
|
||||
BorderBrush="{Binding Path=IsSelected, Converter={StaticResource BooleanToBrushConverter}}"
|
||||
Style="{StaticResource templateBackground}"
|
||||
MouseDown="LayoutItem_Click">
|
||||
<DockPanel Margin="0,20,0,0"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
LastChildFill="True">
|
||||
<DockPanel DockPanel.Dock="Top" LastChildFill="True" >
|
||||
<Button x:Name="DeleteButton" Visibility="{Binding Converter={StaticResource ModelToVisibilityConverter}}" DockPanel.Dock="Right" MaxHeight="10" Click="OnDelete" Padding="8,4,8,4" Margin="0,0,8,0" BorderThickness="0" Background="#f2f2f2">
|
||||
<Image Source="images/Delete.png" />
|
||||
</Button>
|
||||
<TextBlock DockPanel.Dock="Top"
|
||||
TextTrimming="CharacterEllipsis" Padding="8,0,8,0"
|
||||
Text="{Binding Name}"
|
||||
Style="{StaticResource templateTitleText}" />
|
||||
</DockPanel>
|
||||
<local:LayoutPreview Margin="16" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,16">
|
||||
<Button x:Name="EditCustomButton" Content="Edit selected layout" Padding="8" Style="{StaticResource secondaryButton}" Click="EditLayout_Click"/>
|
||||
<Button x:Name="ApplyCustomButton" Content="Apply" Padding="8" Style="{StaticResource primaryButton}" Click="Apply_Click"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
|
||||
|
||||
</StackPanel>
|
||||
</Controls:MetroWindow>
|
||||
@@ -0,0 +1,218 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using FancyZonesEditor.Models;
|
||||
using MahApps.Metro.Controls;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : MetroWindow
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = _settings;
|
||||
}
|
||||
|
||||
private void DecrementZones_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_settings.ZoneCount > 1)
|
||||
{
|
||||
_settings.ZoneCount--;
|
||||
}
|
||||
}
|
||||
|
||||
private void IncrementZones_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_settings.ZoneCount < 40)
|
||||
{
|
||||
_settings.ZoneCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private Settings _settings = ((App)Application.Current).ZoneSettings;
|
||||
|
||||
private void NewCustomLayoutButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowLayout window = new WindowLayout();
|
||||
window.Show();
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void LayoutItem_Click(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
Select(((Border)sender).DataContext as LayoutModel);
|
||||
}
|
||||
|
||||
private void Select(LayoutModel newSelection)
|
||||
{
|
||||
LayoutModel currentSelection = EditorOverlay.Current.DataContext as LayoutModel;
|
||||
|
||||
if (currentSelection != null)
|
||||
{
|
||||
currentSelection.IsSelected = false;
|
||||
}
|
||||
|
||||
newSelection.IsSelected = true;
|
||||
|
||||
EditorOverlay.Current.DataContext = newSelection;
|
||||
}
|
||||
|
||||
private static string c_defaultNamePrefix = "Custom Layout ";
|
||||
private bool _editing = false;
|
||||
|
||||
private void EditLayout_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_editing = true;
|
||||
this.Close();
|
||||
|
||||
EditorOverlay mainEditor = EditorOverlay.Current;
|
||||
LayoutModel model = mainEditor.DataContext as LayoutModel;
|
||||
if (model == null)
|
||||
{
|
||||
mainEditor.Close();
|
||||
return;
|
||||
}
|
||||
model.IsSelected = false;
|
||||
|
||||
bool isPredefinedLayout = Settings.IsPredefinedLayout(model);
|
||||
|
||||
if (!_settings.CustomModels.Contains(model) || isPredefinedLayout)
|
||||
{
|
||||
if (isPredefinedLayout)
|
||||
{
|
||||
// make a copy
|
||||
model = model.Clone();
|
||||
mainEditor.DataContext = model;
|
||||
}
|
||||
|
||||
int maxCustomIndex = 0;
|
||||
foreach (LayoutModel customModel in _settings.CustomModels)
|
||||
{
|
||||
string name = customModel.Name;
|
||||
if (name.StartsWith(c_defaultNamePrefix))
|
||||
{
|
||||
int i;
|
||||
if (Int32.TryParse(name.Substring(c_defaultNamePrefix.Length), out i))
|
||||
{
|
||||
if (maxCustomIndex < i)
|
||||
{
|
||||
maxCustomIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
model.Name = c_defaultNamePrefix + (++maxCustomIndex);
|
||||
}
|
||||
|
||||
mainEditor.Edit();
|
||||
|
||||
EditorWindow window;
|
||||
if (model is GridLayoutModel)
|
||||
{
|
||||
window = new GridEditorWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
window = new CanvasEditorWindow();
|
||||
}
|
||||
window.Owner = EditorOverlay.Current;
|
||||
window.DataContext = model;
|
||||
window.Show();
|
||||
}
|
||||
|
||||
private void Apply_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
EditorOverlay mainEditor = EditorOverlay.Current;
|
||||
LayoutModel model = mainEditor.DataContext as LayoutModel;
|
||||
if (model != null)
|
||||
{
|
||||
if (model is GridLayoutModel)
|
||||
{
|
||||
model.Apply(mainEditor.GetZoneRects());
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Apply((model as CanvasLayoutModel).Zones.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void OnClosed(object sender, EventArgs e)
|
||||
{
|
||||
if (!_editing)
|
||||
{
|
||||
EditorOverlay.Current.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
foreach(LayoutModel model in _settings.CustomModels)
|
||||
{
|
||||
if (model.IsSelected)
|
||||
{
|
||||
TemplateTab.SelectedIndex = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDelete(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LayoutModel model = ((FrameworkElement)sender).DataContext as LayoutModel;
|
||||
if (model.IsSelected)
|
||||
{
|
||||
OnLoaded(null, null);
|
||||
}
|
||||
model.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class BooleanToBrushConverter : IValueConverter
|
||||
{
|
||||
private static Brush c_selectedBrush = new SolidColorBrush(Color.FromRgb(0x00, 0x78, 0xD7));
|
||||
private static Brush c_normalBrush = new SolidColorBrush(Color.FromRgb(0xF2, 0xF2, 0xF2));
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return ((bool)value) ? c_selectedBrush : c_normalBrush;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return value == c_selectedBrush;
|
||||
}
|
||||
}
|
||||
|
||||
public class ModelToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return Settings.IsPredefinedLayout((LayoutModel)value) ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Converters;
|
||||
using System.Windows.Documents;
|
||||
|
||||
namespace FancyZonesEditor.Models
|
||||
{
|
||||
// CanvasLayoutModel
|
||||
// Free form Layout Model, which specifies independent zone rects
|
||||
public class CanvasLayoutModel : LayoutModel
|
||||
{
|
||||
public CanvasLayoutModel(ushort version, string name, ushort id, byte[] data) : base(name, id)
|
||||
{
|
||||
if (version == c_latestVersion)
|
||||
{
|
||||
Load(data);
|
||||
}
|
||||
}
|
||||
|
||||
public CanvasLayoutModel(string name, ushort id, int referenceWidth, int referenceHeight) : base(name, id)
|
||||
{
|
||||
// Initialize Reference Size
|
||||
_referenceWidth = referenceWidth;
|
||||
_referenceHeight = referenceHeight;
|
||||
}
|
||||
|
||||
public CanvasLayoutModel(string name, ushort id) : base(name, id) { }
|
||||
public CanvasLayoutModel(string name) : base(name) { }
|
||||
public CanvasLayoutModel() : base() { }
|
||||
|
||||
// ReferenceWidth - the reference width for the layout rect that all Zones are relative to
|
||||
public int ReferenceWidth
|
||||
{
|
||||
get { return _referenceWidth; }
|
||||
set
|
||||
{
|
||||
if (_referenceWidth != value)
|
||||
{
|
||||
_referenceWidth = value;
|
||||
FirePropertyChanged("ReferenceWidth");
|
||||
}
|
||||
}
|
||||
}
|
||||
private int _referenceWidth;
|
||||
|
||||
// ReferenceHeight - the reference height for the layout rect that all Zones are relative to
|
||||
public int ReferenceHeight
|
||||
{
|
||||
get { return _referenceHeight; }
|
||||
set
|
||||
{
|
||||
if (_referenceHeight != value)
|
||||
{
|
||||
_referenceHeight = value;
|
||||
FirePropertyChanged("ReferenceHeight");
|
||||
}
|
||||
}
|
||||
}
|
||||
private int _referenceHeight;
|
||||
|
||||
// Zones - the list of all zones in this layout, described as independent rectangles
|
||||
public IList<Int32Rect> Zones { get { return _zones; } }
|
||||
private IList<Int32Rect> _zones = new List<Int32Rect>();
|
||||
|
||||
// RemoveZoneAt
|
||||
// Removes the specified index from the Zones list, and fires a property changed notification for the Zones property
|
||||
public void RemoveZoneAt(int index)
|
||||
{
|
||||
Zones.RemoveAt(index);
|
||||
FirePropertyChanged("Zones");
|
||||
}
|
||||
|
||||
// AddZone
|
||||
// Adds the specified Zone to the end of the Zones list, and fires a property changed notification for the Zones property
|
||||
public void AddZone(Int32Rect zone)
|
||||
{
|
||||
Zones.Add(zone);
|
||||
FirePropertyChanged("Zones");
|
||||
}
|
||||
|
||||
private void Load(byte[] data)
|
||||
{
|
||||
// Initialize this CanvasLayoutModel based on the given persistence data
|
||||
// Skip version (2 bytes), id (2 bytes), and type (1 bytes)
|
||||
int i = 5;
|
||||
_referenceWidth = data[i++] * 256 + data[i++];
|
||||
_referenceHeight = data[i++] * 256 + data[i++];
|
||||
|
||||
int count = data[i++];
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
_zones.Add(new Int32Rect(
|
||||
data[i++] * 256 + data[i++],
|
||||
data[i++] * 256 + data[i++],
|
||||
data[i++] * 256 + data[i++],
|
||||
data[i++] * 256 + data[i++]));
|
||||
}
|
||||
}
|
||||
|
||||
// Clone
|
||||
// Implements the LayoutModel.Clone abstract method
|
||||
// Clones the data from this CanvasLayoutModel to a new CanvasLayoutModel
|
||||
public override LayoutModel Clone()
|
||||
{
|
||||
CanvasLayoutModel layout = new CanvasLayoutModel(Name);
|
||||
layout.ReferenceHeight = ReferenceHeight;
|
||||
layout.ReferenceWidth = ReferenceWidth;
|
||||
|
||||
foreach(Int32Rect zone in Zones)
|
||||
{
|
||||
layout.Zones.Add(zone);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
// GetPersistData
|
||||
// Implements the LayoutModel.GetPersistData abstract method
|
||||
// Returns the state of this GridLayoutModel in persisted format
|
||||
protected override byte[] GetPersistData()
|
||||
{
|
||||
byte[] data = new byte[10 + (_zones.Count * 8)];
|
||||
int i = 0;
|
||||
|
||||
// Common persisted values between all layout types
|
||||
data[i++] = (byte)(c_latestVersion / 256);
|
||||
data[i++] = (byte)(c_latestVersion % 256);
|
||||
data[i++] = 1; // LayoutModelType: 1 == CanvasLayoutModel
|
||||
data[i++] = (byte)(Id / 256);
|
||||
data[i++] = (byte)(Id % 256);
|
||||
// End common
|
||||
|
||||
data[i++] = (byte)(_referenceWidth / 256);
|
||||
data[i++] = (byte)(_referenceWidth % 256);
|
||||
data[i++] = (byte)(_referenceHeight / 256);
|
||||
data[i++] = (byte)(_referenceHeight % 256);
|
||||
data[i++] = (byte)_zones.Count;
|
||||
|
||||
foreach (Int32Rect rect in _zones)
|
||||
{
|
||||
data[i++] = (byte)(rect.X / 256);
|
||||
data[i++] = (byte)(rect.X % 256);
|
||||
|
||||
data[i++] = (byte)(rect.Y / 256);
|
||||
data[i++] = (byte)(rect.Y % 256);
|
||||
|
||||
data[i++] = (byte)(rect.Width / 256);
|
||||
data[i++] = (byte)(rect.Width % 256);
|
||||
|
||||
data[i++] = (byte)(rect.Height / 256);
|
||||
data[i++] = (byte)(rect.Height % 256);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private static ushort c_latestVersion = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Documents;
|
||||
|
||||
namespace FancyZonesEditor.Models
|
||||
{
|
||||
// GridLayoutModel
|
||||
// Grid-styled Layout Model, which specifies rows, columns, percentage sizes, and row/column spans
|
||||
public class GridLayoutModel : LayoutModel
|
||||
{
|
||||
public GridLayoutModel() : base() { }
|
||||
public GridLayoutModel(string name) : base(name) { }
|
||||
public GridLayoutModel(string name, ushort id) : base(name, id) { }
|
||||
public GridLayoutModel(ushort version, string name, ushort id, byte[] data) : base(name, id)
|
||||
{
|
||||
if (version == c_latestVersion)
|
||||
{
|
||||
Reload(data);
|
||||
}
|
||||
}
|
||||
// Rows - number of rows in the Grid
|
||||
public int Rows
|
||||
{
|
||||
get { return _rows; }
|
||||
set
|
||||
{
|
||||
if (_rows != value)
|
||||
{
|
||||
_rows = value;
|
||||
FirePropertyChanged("Rows");
|
||||
}
|
||||
}
|
||||
}
|
||||
private int _rows = 1;
|
||||
|
||||
// Columns - number of columns in the Grid
|
||||
public int Columns
|
||||
{
|
||||
get { return _cols; }
|
||||
set
|
||||
{
|
||||
if (_cols != value)
|
||||
{
|
||||
_cols = value;
|
||||
FirePropertyChanged("Columns");
|
||||
}
|
||||
}
|
||||
}
|
||||
private int _cols = 1;
|
||||
|
||||
// CellChildMap - represents which "children" belong in which grid cells;
|
||||
// shows spanning children by the same index appearing in adjacent cells
|
||||
// TODO: ideally no setter here - this means moving logic like "split" over to model
|
||||
public int[,] CellChildMap { get { return _cellChildMap; } set { _cellChildMap = value; } }
|
||||
private int[,] _cellChildMap;
|
||||
|
||||
// RowPercents - represents the %age height of each row in the grid
|
||||
public int[] RowPercents { get { return _rowPercents; } set { _rowPercents = value; } }
|
||||
private int[] _rowPercents;
|
||||
|
||||
// ColumnPercents - represents the %age width of each column in the grid
|
||||
public int[] ColumnPercents { get { return _colPercents; } set { _colPercents = value; } }
|
||||
private int[] _colPercents;
|
||||
|
||||
// FreeZones (not persisted) - used to keep track of child indices that are no longer in use in the CellChildMap,
|
||||
// making them candidates for re-use when it's needed to add another child
|
||||
// TODO: do I need FreeZones on the data model? - I think I do
|
||||
public IList<int> FreeZones { get { return _freeZones; } }
|
||||
private IList<int> _freeZones = new List<int>();
|
||||
|
||||
public void Reload(byte[] data)
|
||||
{
|
||||
// Skip version (2 bytes), id (2 bytes), and type (1 bytes)
|
||||
int i = 5;
|
||||
|
||||
Rows = data[i++];
|
||||
Columns = data[i++];
|
||||
|
||||
_rowPercents = new int[Rows];
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
_rowPercents[row] = data[i++]*256 + data[i++];
|
||||
}
|
||||
|
||||
_colPercents = new int[Columns];
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
_colPercents[col] = data[i++]*256 + data[i++];
|
||||
}
|
||||
|
||||
_cellChildMap = new int[Rows, Columns];
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
_cellChildMap[row, col] = data[i++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone
|
||||
// Implements the LayoutModel.Clone abstract method
|
||||
// Clones the data from this GridLayoutModel to a new GridLayoutModel
|
||||
public override LayoutModel Clone()
|
||||
{
|
||||
GridLayoutModel layout = new GridLayoutModel(Name);
|
||||
int rows = Rows;
|
||||
int cols = Columns;
|
||||
|
||||
layout.Rows = rows;
|
||||
layout.Columns = cols;
|
||||
|
||||
int[,] cellChildMap = new int[rows, cols];
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
cellChildMap[row, col] = CellChildMap[row, col];
|
||||
}
|
||||
}
|
||||
layout.CellChildMap = cellChildMap;
|
||||
|
||||
int[] rowPercents = new int[rows];
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
rowPercents[row] = RowPercents[row];
|
||||
}
|
||||
layout.RowPercents = rowPercents;
|
||||
|
||||
int[] colPercents = new int[cols];
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
colPercents[col] = ColumnPercents[col];
|
||||
}
|
||||
layout.ColumnPercents = colPercents;
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
// GetPersistData
|
||||
// Implements the LayoutModel.GetPersistData abstract method
|
||||
// Returns the state of this GridLayoutModel in persisted format
|
||||
protected override byte[] GetPersistData()
|
||||
{
|
||||
int rows = Rows;
|
||||
int cols = Columns;
|
||||
|
||||
int[,] cellChildMap;
|
||||
|
||||
if (_freeZones.Count == 0)
|
||||
{
|
||||
// no unused indices -- so we can just use the _cellChildMap as is
|
||||
cellChildMap = _cellChildMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
// compress cellChildMap to not have gaps for unused child indices;
|
||||
List<int> mapping = new List<int>();
|
||||
|
||||
cellChildMap = new int[rows, cols];
|
||||
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
int source = _cellChildMap[row, col];
|
||||
|
||||
int index = mapping.IndexOf(source);
|
||||
if (index == -1)
|
||||
{
|
||||
index = mapping.Count;
|
||||
mapping.Add(source);
|
||||
}
|
||||
cellChildMap[row, col] = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte[] data = new byte[7 + (Rows * 2) + (Columns * 2) + (Rows * Columns)];
|
||||
|
||||
int i = 0;
|
||||
// Common persisted values between all layout types
|
||||
data[i++] = (byte)(c_latestVersion / 256);
|
||||
data[i++] = (byte)(c_latestVersion % 256);
|
||||
data[i++] = 0; // LayoutModelType: 0 == GridLayoutModel
|
||||
data[i++] = (byte)(Id / 256);
|
||||
data[i++] = (byte)(Id % 256);
|
||||
// End common
|
||||
|
||||
data[i++] = (byte)Rows;
|
||||
data[i++] = (byte)Columns;
|
||||
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
int rowPercent = _rowPercents[row];
|
||||
data[i++] = (byte)(rowPercent / 256);
|
||||
data[i++] = (byte)(rowPercent % 256);
|
||||
}
|
||||
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
int colPercent = _colPercents[col];
|
||||
data[i++] = (byte)(colPercent / 256);
|
||||
data[i++] = (byte)(colPercent % 256);
|
||||
}
|
||||
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
data[i++] = (byte)cellChildMap[row, col];
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private static ushort c_latestVersion = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace FancyZonesEditor.Models
|
||||
{
|
||||
// Base LayoutModel
|
||||
// Manages common properties and base persistence
|
||||
public abstract class LayoutModel : INotifyPropertyChanged
|
||||
{
|
||||
protected LayoutModel() { }
|
||||
|
||||
protected LayoutModel(string name) : this()
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
protected LayoutModel(string name, ushort id) : this(name)
|
||||
{
|
||||
_id = id;
|
||||
}
|
||||
|
||||
// Name - the display name for this layout model - is also used as the key in the registry
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
set
|
||||
{
|
||||
if (_name != value)
|
||||
{
|
||||
_name = value;
|
||||
FirePropertyChanged("Name");
|
||||
}
|
||||
}
|
||||
}
|
||||
private string _name;
|
||||
|
||||
// Id - the unique ID for this layout model - is used to connect fancy zones' ZonesSets with the editor's Layouts
|
||||
// - note: 0 means this is a new layout, which means it will have its ID auto-assigned on persist
|
||||
public ushort Id
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_id == 0)
|
||||
{
|
||||
_id = ++s_maxId;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
}
|
||||
private ushort _id = 0;
|
||||
|
||||
// IsSelected (not-persisted) - tracks whether or not this LayoutModel is selected in the picker
|
||||
// TODO: once we switch to a picker per monitor, we need to move this state to the view
|
||||
public bool IsSelected
|
||||
{
|
||||
get { return _isSelected; }
|
||||
set
|
||||
{
|
||||
if (_isSelected != value)
|
||||
{
|
||||
_isSelected = value;
|
||||
FirePropertyChanged("IsSelected");
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool _isSelected;
|
||||
|
||||
// implementation of INotifyProeprtyChanged
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
// FirePropertyChanged -- wrapper that calls INPC.PropertyChanged
|
||||
protected virtual void FirePropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChangedEventHandler handler = PropertyChanged;
|
||||
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
// Removes this Layout from the registry and the loaded CustomModels list
|
||||
public void Delete()
|
||||
{
|
||||
RegistryKey key = Registry.CurrentUser.OpenSubKey(c_registryPath, true);
|
||||
if (key != null)
|
||||
{
|
||||
key.DeleteValue(Name);
|
||||
}
|
||||
|
||||
int i = s_customModels.IndexOf(this);
|
||||
if (i != -1)
|
||||
{
|
||||
s_customModels.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Loads all the Layouts persisted under the Layouts key in the registry
|
||||
public static ObservableCollection<LayoutModel> LoadCustomModels()
|
||||
{
|
||||
s_customModels = new ObservableCollection<LayoutModel>();
|
||||
|
||||
RegistryKey key = Registry.CurrentUser.OpenSubKey(c_registryPath);
|
||||
if (key != null)
|
||||
{
|
||||
foreach (string name in key.GetValueNames())
|
||||
{
|
||||
LayoutModel model = null;
|
||||
byte[] data = (byte[])Registry.GetValue(c_fullRegistryPath, name, null);
|
||||
|
||||
ushort version = (ushort) (data[0]*256 + data[1]);
|
||||
byte type = data[2];
|
||||
ushort id = (ushort) (data[3]*256 + data[4]);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0: model = new GridLayoutModel(version, name, id, data); break;
|
||||
case 1: model = new CanvasLayoutModel(version, name, id, data); break;
|
||||
}
|
||||
|
||||
if (model != null)
|
||||
{
|
||||
if (s_maxId < id)
|
||||
{
|
||||
s_maxId = id;
|
||||
}
|
||||
s_customModels.Add(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s_customModels;
|
||||
}
|
||||
private static ObservableCollection<LayoutModel> s_customModels = null;
|
||||
|
||||
private static ushort s_maxId = 0;
|
||||
|
||||
// Callbacks that the base LayoutModel makes to derived types
|
||||
protected abstract byte[] GetPersistData();
|
||||
public abstract LayoutModel Clone();
|
||||
|
||||
// PInvokes to handshake with fancyzones backend
|
||||
internal static class Native
|
||||
{
|
||||
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
|
||||
public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
|
||||
|
||||
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
|
||||
|
||||
internal delegate int PersistZoneSet(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string activeKey,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string key,
|
||||
ushort layoutId,
|
||||
int zoneCount,
|
||||
[MarshalAs(UnmanagedType.LPArray)] int[] zoneArray);
|
||||
}
|
||||
|
||||
public void Persist(System.Windows.Int32Rect[] zones)
|
||||
{
|
||||
// Persist the editor data
|
||||
Registry.SetValue(c_fullRegistryPath, Name, GetPersistData(), Microsoft.Win32.RegistryValueKind.Binary);
|
||||
Apply(zones);
|
||||
}
|
||||
|
||||
public void Apply(System.Windows.Int32Rect[] zones)
|
||||
{
|
||||
// Persist the zone data back into FZ
|
||||
var module = Native.LoadLibrary("fancyzones.dll");
|
||||
if (module == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pfn = Native.GetProcAddress(module, "PersistZoneSet");
|
||||
if (pfn == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale all the zones to the DPI and then pack them up to be marshalled.
|
||||
int zoneCount = zones.Length;
|
||||
var zoneArray = new int[zoneCount * 4];
|
||||
var graphics = System.Drawing.Graphics.FromHwnd(IntPtr.Zero);
|
||||
float dpi = graphics.DpiX / 96;
|
||||
for (int i = 0; i < zones.Length; i++)
|
||||
{
|
||||
var left = (int)(zones[i].X * dpi);
|
||||
var top = (int)(zones[i].Y * dpi);
|
||||
var right = left + (int)(zones[i].Width * dpi);
|
||||
var bottom = top + (int)(zones[i].Height * dpi);
|
||||
|
||||
var index = i * 4;
|
||||
zoneArray[index] = left;
|
||||
zoneArray[index+1] = top;
|
||||
zoneArray[index+2] = right;
|
||||
zoneArray[index+3] = bottom;
|
||||
}
|
||||
|
||||
string[] args = Environment.GetCommandLineArgs();
|
||||
if (args.Length > 1)
|
||||
{
|
||||
// args[1] = registry key value of currently active ZoneSet
|
||||
// args[2] = id of layout to load at startup
|
||||
|
||||
string uniqueId = args[1];
|
||||
|
||||
// TODO: multimon
|
||||
double height = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;
|
||||
double width = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;
|
||||
var key = width.ToString() + "_" + height.ToString();
|
||||
|
||||
var persistZoneSet = Marshal.GetDelegateForFunctionPointer<Native.PersistZoneSet>(pfn);
|
||||
persistZoneSet(uniqueId, key, _id, zoneCount, zoneArray);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly string c_registryPath = Settings.RegistryPath + "\\Layouts";
|
||||
private static readonly string c_fullRegistryPath = Settings.FullRegistryPath + "\\Layouts";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.ComponentModel;
|
||||
using System.Collections;
|
||||
using System.Collections.ObjectModel;
|
||||
using FancyZonesEditor.Models;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
//
|
||||
// Settings
|
||||
// These are the configuration settings used by the rest of the editor
|
||||
// Other UIs in the editor will subscribe to change events on the properties to stay up to date as these properties change
|
||||
//
|
||||
public class Settings : INotifyPropertyChanged
|
||||
{
|
||||
public Settings()
|
||||
{
|
||||
Rect workArea = System.Windows.SystemParameters.WorkArea;
|
||||
|
||||
// Initialize the five default layout models: Focus, Columns, Rows, Grid, and PriorityGrid
|
||||
_defaultModels = new List<LayoutModel>(5);
|
||||
_focusModel = new CanvasLayoutModel("Focus", c_focusModelId, (int)workArea.Width, (int)workArea.Height);
|
||||
_defaultModels.Add(_focusModel);
|
||||
|
||||
_columnsModel = new GridLayoutModel("Columns", c_columnsModelId);
|
||||
_columnsModel.Rows = 1;
|
||||
_columnsModel.RowPercents = new int[1] { c_multiplier };
|
||||
_defaultModels.Add(_columnsModel);
|
||||
|
||||
_rowsModel = new GridLayoutModel("Rows", c_rowsModelId);
|
||||
_rowsModel.Columns = 1;
|
||||
_rowsModel.ColumnPercents = new int[1] { c_multiplier };
|
||||
_defaultModels.Add(_rowsModel);
|
||||
|
||||
_gridModel = new GridLayoutModel("Grid", c_gridModelId);
|
||||
_defaultModels.Add(_gridModel);
|
||||
|
||||
_priorityGridModel = new GridLayoutModel("Priority Grid", c_priorityGridModelId);
|
||||
_defaultModels.Add(_priorityGridModel);
|
||||
|
||||
_blankCustomModel = new CanvasLayoutModel("Create new custom", c_blankCustomModelId, (int)workArea.Width, (int)workArea.Height);
|
||||
|
||||
_zoneCount = (int)Registry.GetValue(FullRegistryPath, "ZoneCount", 3);
|
||||
_spacing = (int)Registry.GetValue(FullRegistryPath, "Spacing", 16);
|
||||
_showSpacing = (int)Registry.GetValue(FullRegistryPath, "ShowSpacing", 1) == 1;
|
||||
|
||||
UpdateLayoutModels();
|
||||
}
|
||||
|
||||
// ZoneCount - number of zones selected in the picker window
|
||||
public int ZoneCount
|
||||
{
|
||||
get { return _zoneCount; }
|
||||
set
|
||||
{
|
||||
if (_zoneCount != value)
|
||||
{
|
||||
_zoneCount = value;
|
||||
Registry.SetValue(FullRegistryPath, "ZoneCount", _zoneCount, RegistryValueKind.DWord);
|
||||
UpdateLayoutModels();
|
||||
FirePropertyChanged("ZoneCount");
|
||||
}
|
||||
}
|
||||
}
|
||||
private int _zoneCount;
|
||||
|
||||
// Spacing - how much space in between zones of the grid do you want
|
||||
public int Spacing
|
||||
{
|
||||
get { return _spacing; }
|
||||
set
|
||||
{
|
||||
if (_spacing != value)
|
||||
{
|
||||
_spacing = value;
|
||||
Registry.SetValue(FullRegistryPath, "Spacing", _spacing, RegistryValueKind.DWord);
|
||||
FirePropertyChanged("Spacing");
|
||||
}
|
||||
}
|
||||
}
|
||||
private int _spacing;
|
||||
|
||||
// ShowSpacing - is the Spacing value used or ignored?
|
||||
public bool ShowSpacing
|
||||
{
|
||||
get { return _showSpacing; }
|
||||
set
|
||||
{
|
||||
if (_showSpacing != value)
|
||||
{
|
||||
_showSpacing = value;
|
||||
Registry.SetValue(FullRegistryPath, "ShowSpacing", _showSpacing, RegistryValueKind.DWord);
|
||||
FirePropertyChanged("ShowSpacing");
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool _showSpacing;
|
||||
|
||||
// IsShiftKeyPressed - is the shift key currently being held down
|
||||
public bool IsShiftKeyPressed
|
||||
{
|
||||
get { return _isShiftKeyPressed; }
|
||||
set
|
||||
{
|
||||
if (_isShiftKeyPressed != value)
|
||||
{
|
||||
_isShiftKeyPressed = value;
|
||||
FirePropertyChanged("IsShiftKeyPressed");
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool _isShiftKeyPressed;
|
||||
|
||||
// IsCtrlKeyPressed - is the ctrl key currently being held down
|
||||
public bool IsCtrlKeyPressed
|
||||
{
|
||||
get { return _isCtrlKeyPressed; }
|
||||
set
|
||||
{
|
||||
if (_isCtrlKeyPressed != value)
|
||||
{
|
||||
_isCtrlKeyPressed = value;
|
||||
FirePropertyChanged("IsCtrlKeyPressed");
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool _isCtrlKeyPressed;
|
||||
|
||||
// UpdateLayoutModels
|
||||
// Update the five default layouts based on the new ZoneCount
|
||||
private void UpdateLayoutModels()
|
||||
{
|
||||
int previousZoneCount = _focusModel.Zones.Count;
|
||||
|
||||
// Update the "Focus" Default Layout
|
||||
_focusModel.Zones.Clear();
|
||||
|
||||
Int32Rect focusZoneRect = new Int32Rect((int)(_focusModel.ReferenceWidth * 0.1), (int)(_focusModel.ReferenceHeight * 0.1), (int)(_focusModel.ReferenceWidth * 0.6), (int)(_focusModel.ReferenceHeight * 0.6));
|
||||
int focusRectXIncrement = (ZoneCount <= 1) ? 0 : (int)(_focusModel.ReferenceWidth * 0.2) / (ZoneCount - 1);
|
||||
int focusRectYIncrement = (ZoneCount <= 1) ? 0 : (int)(_focusModel.ReferenceHeight * 0.2) / (ZoneCount - 1);
|
||||
|
||||
for (int i = 0; i < ZoneCount; i++)
|
||||
{
|
||||
_focusModel.Zones.Add(focusZoneRect);
|
||||
focusZoneRect.X += focusRectXIncrement;
|
||||
focusZoneRect.Y += focusRectYIncrement;
|
||||
}
|
||||
|
||||
// Update the "Rows" and "Columns" Default Layouts
|
||||
// They can share their model, just transposed
|
||||
_rowsModel.CellChildMap = new int[ZoneCount, 1];
|
||||
_columnsModel.CellChildMap = new int[1, ZoneCount];
|
||||
_rowsModel.Rows = _columnsModel.Columns = ZoneCount;
|
||||
_rowsModel.RowPercents = _columnsModel.ColumnPercents = new int[ZoneCount];
|
||||
|
||||
for (int i = 0; i < ZoneCount; i++)
|
||||
{
|
||||
_rowsModel.CellChildMap[i, 0] = i;
|
||||
_columnsModel.CellChildMap[0, i] = i;
|
||||
_rowsModel.RowPercents[i] = c_multiplier / ZoneCount; // _columnsModel is sharing the same array
|
||||
}
|
||||
|
||||
// Update the "Grid" Default Layout
|
||||
int rows = 1;
|
||||
int cols = 1;
|
||||
int mergeCount = 0;
|
||||
while (ZoneCount / rows >= rows)
|
||||
{
|
||||
rows++;
|
||||
}
|
||||
rows--;
|
||||
cols = ZoneCount / rows;
|
||||
if (ZoneCount % rows == 0)
|
||||
{
|
||||
// even grid
|
||||
}
|
||||
else
|
||||
{
|
||||
cols++;
|
||||
mergeCount = rows - (ZoneCount % rows);
|
||||
}
|
||||
_gridModel.Rows = rows;
|
||||
_gridModel.Columns = cols;
|
||||
_gridModel.RowPercents = new int[rows];
|
||||
_gridModel.ColumnPercents = new int[cols];
|
||||
_gridModel.CellChildMap = new int[rows, cols];
|
||||
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
_gridModel.RowPercents[row] = c_multiplier / rows;
|
||||
}
|
||||
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
_gridModel.ColumnPercents[col] = c_multiplier / cols;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (int col = cols - 1; col >= 0; col--)
|
||||
{
|
||||
for (int row = rows - 1; row >= 0; row--)
|
||||
{
|
||||
_gridModel.CellChildMap[row, col] = index++;
|
||||
if (index == ZoneCount)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Update the "Priority Grid" Default Layout
|
||||
if (ZoneCount <= s_priorityData.Length)
|
||||
{
|
||||
_priorityGridModel.Reload(s_priorityData[ZoneCount - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// same as grid;
|
||||
_priorityGridModel.Rows = _gridModel.Rows;
|
||||
_priorityGridModel.Columns = _gridModel.Columns;
|
||||
_priorityGridModel.RowPercents = _gridModel.RowPercents;
|
||||
_priorityGridModel.ColumnPercents = _gridModel.ColumnPercents;
|
||||
_priorityGridModel.CellChildMap = _gridModel.CellChildMap;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<LayoutModel> DefaultModels { get { return _defaultModels; } }
|
||||
public ObservableCollection<LayoutModel> CustomModels
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_customModels == null)
|
||||
{
|
||||
_customModels = LayoutModel.LoadCustomModels();
|
||||
_customModels.Insert(0, _blankCustomModel);
|
||||
}
|
||||
return _customModels;
|
||||
}
|
||||
}
|
||||
private ObservableCollection<LayoutModel> _customModels;
|
||||
|
||||
public static readonly string RegistryPath = "SOFTWARE\\SuperFancyZones";
|
||||
public static readonly string FullRegistryPath = "HKEY_CURRENT_USER\\" + RegistryPath;
|
||||
|
||||
public static bool IsPredefinedLayout(LayoutModel model)
|
||||
{
|
||||
return (model.Id >= c_lastPrefinedId);
|
||||
}
|
||||
|
||||
// implementation of INotifyProeprtyChanged
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
// FirePropertyChanged -- wrapper that calls INPC.PropertyChanged
|
||||
protected virtual void FirePropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChangedEventHandler handler = PropertyChanged;
|
||||
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
// storage for Default Layout Models
|
||||
private IList<LayoutModel> _defaultModels;
|
||||
private CanvasLayoutModel _focusModel;
|
||||
private GridLayoutModel _rowsModel;
|
||||
private GridLayoutModel _columnsModel;
|
||||
private GridLayoutModel _gridModel;
|
||||
private GridLayoutModel _priorityGridModel;
|
||||
private CanvasLayoutModel _blankCustomModel;
|
||||
|
||||
private static readonly ushort c_focusModelId = 0xFFFF;
|
||||
private static readonly ushort c_rowsModelId = 0xFFFE;
|
||||
private static readonly ushort c_columnsModelId = 0xFFFD;
|
||||
private static readonly ushort c_gridModelId = 0xFFFC;
|
||||
private static readonly ushort c_priorityGridModelId = 0xFFFB;
|
||||
private static readonly ushort c_blankCustomModelId = 0xFFFA;
|
||||
private static readonly ushort c_lastPrefinedId = c_blankCustomModelId;
|
||||
|
||||
// hard coded data for all the "Priority Grid" configurations that are unique to "Grid"
|
||||
private static byte[][] s_priorityData = new byte[][]
|
||||
{
|
||||
new byte[] { 0, 0, 0, 0, 0, 1, 1, 39, 16, 39, 16, 0 },
|
||||
new byte[] { 0, 0, 0, 0, 0, 1, 2, 39, 16, 26, 11, 13, 5, 0, 1 },
|
||||
new byte[] { 0, 0, 0, 0, 0, 1, 3, 39, 16, 9, 196, 19, 136, 9, 196, 0, 1, 2 },
|
||||
new byte[] { 0, 0, 0, 0, 0, 2, 3, 19, 136, 19, 136, 9, 196, 19, 136, 9, 196, 0, 1, 2, 0, 1, 3 },
|
||||
new byte[] { 0, 0, 0, 0, 0, 2, 3, 19, 136, 19, 136, 9, 196, 19, 136, 9, 196, 0, 1, 2, 3, 1, 4 },
|
||||
new byte[] { 0, 0, 0, 0, 0, 3, 3, 13, 5, 13, 6, 13, 5, 9, 196, 19, 136, 9, 196, 0, 1, 2, 0, 1, 3, 4, 1, 5 },
|
||||
new byte[] { 0, 0, 0, 0, 0, 3, 3, 13, 5, 13, 6, 13, 5, 9, 196, 19, 136, 9, 196, 0, 1, 2, 3, 1, 4, 5, 1, 6 },
|
||||
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 2, 5, 6, 1, 2, 7 },
|
||||
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 2, 5, 6, 1, 7, 8 },
|
||||
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 5, 6, 7, 1, 8, 9 },
|
||||
new byte[] { 0, 0, 0, 0, 0, 3, 4, 13, 5, 13, 6, 13, 5, 9, 196, 9, 196, 9, 196, 9, 196, 0, 1, 2, 3, 4, 1, 5, 6, 7, 8, 9, 10 }
|
||||
};
|
||||
|
||||
private const int c_multiplier = 10000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("FancyZonesEditor")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft Corp.")]
|
||||
[assembly: AssemblyProduct("FancyZonesEditor")]
|
||||
[assembly: AssemblyCopyright("Copyright (C) 2019 Microsoft Corp.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("0.11.0.0")]
|
||||
[assembly: AssemblyFileVersion("0.11.0.0")]
|
||||
63
src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs
generated
Normal file
63
src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace FancyZonesEditor.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FancyZonesEditor.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
26
src/modules/fancyzones/editor/FancyZonesEditor/Properties/Settings.Designer.cs
generated
Normal file
26
src/modules/fancyzones/editor/FancyZonesEditor/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace FancyZonesEditor.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.1.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
46
src/modules/fancyzones/editor/FancyZonesEditor/RowColInfo.cs
Normal file
46
src/modules/fancyzones/editor/FancyZonesEditor/RowColInfo.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
public class RowColInfo
|
||||
{
|
||||
public RowColInfo(int percent)
|
||||
{
|
||||
Percent = percent;
|
||||
}
|
||||
|
||||
public RowColInfo(int index, int count)
|
||||
{
|
||||
Percent = (c_multiplier / count) + ((index == 0) ? (c_multiplier % count) : 0);
|
||||
}
|
||||
|
||||
private const int c_multiplier = 10000;
|
||||
|
||||
public double SetExtent(double start, double totalExtent)
|
||||
{
|
||||
Start = start;
|
||||
Extent = totalExtent * Percent / c_multiplier;
|
||||
End = Start + Extent;
|
||||
return Extent;
|
||||
}
|
||||
|
||||
public RowColInfo[] Split(double offset)
|
||||
{
|
||||
RowColInfo[] info = new RowColInfo[2];
|
||||
|
||||
int newPercent = (int)(Percent * offset / Extent);
|
||||
info[0] = new RowColInfo(newPercent);
|
||||
info[1] = new RowColInfo(Percent - newPercent);
|
||||
return info;
|
||||
}
|
||||
|
||||
public int Percent;
|
||||
public double Extent;
|
||||
public double Start;
|
||||
public double End;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<Window x:Class="FancyZonesEditor.WindowLayout"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
Title="Window1" Height="450" Width="800"
|
||||
WindowState="Maximized"
|
||||
ShowInTaskbar="False"
|
||||
ResizeMode="NoResize"
|
||||
WindowStyle="None"
|
||||
AllowsTransparency="True"
|
||||
Background="Transparent"
|
||||
Loaded="onLoad"
|
||||
>
|
||||
|
||||
|
||||
<Grid x:Name="Body">
|
||||
<Rectangle Fill="White" Opacity="0.5"/>
|
||||
|
||||
<Grid x:Name="Window1" >
|
||||
<Border BorderThickness="2" BorderBrush="Black">
|
||||
<Grid>
|
||||
<!--
|
||||
<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"/>
|
||||
<!--
|
||||
<Grid Width="24" Height="24" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,10,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Rectangle Fill="White" Height="24" Width="2" Margin="-33,0,0,0">
|
||||
<Rectangle.RenderTransform>
|
||||
<RotateTransform Angle="-45"/>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Rectangle Fill="White" Height="24" Width="2" Margin="0,-3,0,0" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Rectangle.RenderTransform>
|
||||
<RotateTransform Angle="45"/>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
</Grid>
|
||||
-->
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace FancyZonesEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for Window1.xaml
|
||||
/// </summary>
|
||||
public partial class WindowLayout : Window
|
||||
{
|
||||
public WindowLayout()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
void onLoad(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//WindowEditor window = new WindowEditor(); window.Show();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 434 B |
BIN
src/modules/fancyzones/editor/FancyZonesEditor/images/Delete.png
Normal file
BIN
src/modules/fancyzones/editor/FancyZonesEditor/images/Delete.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 317 B |
BIN
src/modules/fancyzones/editor/FancyZonesEditor/images/Merge.png
Normal file
BIN
src/modules/fancyzones/editor/FancyZonesEditor/images/Merge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 279 B |
Reference in New Issue
Block a user