mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-08 20:27:36 +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
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);
|
||||
}
|
||||
Reference in New Issue
Block a user