diff --git a/src/Perspex.Controls/GridSplitter.cs b/src/Perspex.Controls/GridSplitter.cs index a5228d3862..b6a16a898d 100644 --- a/src/Perspex.Controls/GridSplitter.cs +++ b/src/Perspex.Controls/GridSplitter.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.Collections.Generic; +using System.Linq; using Perspex.Collections; using Perspex.Controls.Primitives; @@ -11,8 +13,11 @@ using Perspex.VisualTree; namespace Perspex.Controls { /// - /// Unlike WPF GridSplitter, Perspex GridSplitter has only one Behavior, GridResizeBehavior.PreviousAndNext + /// Represents the control that redistributes space between columns or rows of a Grid control. /// + /// + /// Unlike WPF GridSplitter, Perspex GridSplitter has only one Behavior, GridResizeBehavior.PreviousAndNext. + /// public class GridSplitter : Thumb { /// @@ -23,93 +28,58 @@ namespace Perspex.Controls protected Grid _grid; - private IGridColumnsResizer _resizer; + private DefinitionBase _prevDefinition; - /// - /// Gets or sets the orientation of the GridsSlitter, if null, it's inferred from column/row defenition(should be auto). - /// - public Orientation? Orientation { get { return GetValue(OrientationProperty); } set { SetValue(OrientationProperty, value); } } + private DefinitionBase _nextDefinition; + private bool _isResizingColumns; - static GridSplitter() - { - PseudoClass(OrientationProperty, o => o == Perspex.Controls.Orientation.Vertical, ":vertical"); - PseudoClass(OrientationProperty, o => o == Perspex.Controls.Orientation.Horizontal, ":horizontal"); - } - - - protected override void OnDragDelta(VectorEventArgs e) - { - _resizer.DragDelta(e); - } + private List _definitions; /// - /// If orientation is not set, method automatically calculates orientation based column/row auto size + /// Gets or sets the orientation of the GridsSlitter. /// - /// - private void AutoSetOrientation() - { - if (Orientation.HasValue) + /// + /// if null, it's inferred from column/row definition (should be auto). + /// + public Orientation? Orientation { + get { - return; + return GetValue(OrientationProperty); } - if (_grid.ColumnDefinitions[GetValue(Grid.ColumnProperty)].Width.IsAuto) - { - Orientation = Perspex.Controls.Orientation.Vertical; - return; - } - if (_grid.RowDefinitions[GetValue(Grid.RowProperty)].Height.IsAuto) + set { - Orientation = Perspex.Controls.Orientation.Horizontal; - return; + SetValue(OrientationProperty, value); } - throw new InvalidOperationException("GridSpliter Should have Orientation, width or height set."); } - - protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + + static GridSplitter() { - _grid = this.GetVisualParent(); - AutoSetOrientation(); - switch (Orientation) - { - case Perspex.Controls.Orientation.Vertical: - _resizer = new VerticalColumnsResizer(_grid, GetValue(Grid.ColumnProperty)); - break; - case Perspex.Controls.Orientation.Horizontal: - _resizer = new HorizontalGridColumnsResizer(_grid, GetValue(Grid.RowProperty)); - break; - default: - throw new ArgumentOutOfRangeException(); - } - base.OnAttachedToVisualTree(e); + PseudoClass(OrientationProperty, o => o == Perspex.Controls.Orientation.Vertical, ":vertical"); + PseudoClass(OrientationProperty, o => o == Perspex.Controls.Orientation.Horizontal, ":horizontal"); } - } - internal interface IGridColumnsResizer - { - void DragDelta(VectorEventArgs e); - } - - internal abstract class GridColumnsResizer : IGridColumnsResizer - where T : DefinitionBase - { - protected PerspexList _definitions; - - protected T _nextDefinition; - - protected T _prevDefinition; + private void GetDeltaConstraints(out double min, out double max) + { + double prevDefinitionLen = GetActualLength(_prevDefinition); + double prevDefinitionMin = GetMinLength(_prevDefinition); + double prevDefinitionMax = GetMaxLength(_prevDefinition); - public abstract Cursor Cursor { get; } + double nextDefinitionLen = GetActualLength(_nextDefinition); + double nextDefinitionMin = GetMinLength(_nextDefinition); + double nextDefinitionMax = GetMaxLength(_nextDefinition); + // Determine the minimum and maximum the columns can be resized + min = -Math.Min(prevDefinitionLen - prevDefinitionMin, nextDefinitionMax - nextDefinitionLen); + max = Math.Min(prevDefinitionMax - prevDefinitionLen, nextDefinitionLen - nextDefinitionMin); + } - public void DragDelta(VectorEventArgs e) + protected override void OnDragDelta(VectorEventArgs e) { - var delta = GetDelta(e); - + var delta = Orientation.Value == Perspex.Controls.Orientation.Vertical ? e.Vector.X : e.Vector.Y; double max; double min; GetDeltaConstraints(out min, out max); delta = Math.Min(Math.Max(delta, min), max); - foreach (var definition in _definitions) { if (definition == _prevDefinition) @@ -122,120 +92,92 @@ namespace Perspex.Controls } else if (IsStar(definition)) { - SetLengthInStars(definition, GetActualLength(definition)); // same size but in stars + SetLengthInStars(definition, GetActualLength(definition)); // same size but in stars. } } } - protected abstract double GetActualLength(T definition); - - protected abstract double GetMinLength(T definition); - - protected abstract double GetMaxLength(T definition); - - protected abstract bool IsStar(T definition); - - protected abstract void SetLengthInStars(T definition, double value); - - protected abstract double GetDelta(VectorEventArgs vectorEventArgs); - - protected void GetDeltaConstraints(out double min, out double max) - { - var _prevDefinitionLen = GetActualLength(_prevDefinition); - var _prevDefinitionMin = GetMinLength(_prevDefinition); - var _prevDefinitionMax = GetMaxLength(_prevDefinition); - - var _nextDefinitionLen = GetActualLength(_nextDefinition); - var _nextDefinitionMin = GetMinLength(_nextDefinition); - var _nextDefinitionMax = GetMaxLength(_nextDefinition); - - // Determine the minimum and maximum the columns can be resized - min = -Math.Min(_prevDefinitionLen - _prevDefinitionMin, _nextDefinitionMax - _nextDefinitionLen); - max = Math.Min(_prevDefinitionMax - _prevDefinitionLen, _nextDefinitionLen - _nextDefinitionMin); - } - } - - internal class HorizontalGridColumnsResizer : GridColumnsResizer - { - public HorizontalGridColumnsResizer(Grid _grid, int splitterRow) + /// + /// If orientation is not set, method automatically calculates orientation based column/row auto size. + /// + private void AutoSetOrientation() { - _definitions = _grid.RowDefinitions; - _nextDefinition = _definitions[splitterRow + 1]; - _prevDefinition = _definitions[splitterRow - 1]; + if (Orientation.HasValue) + { + return; + } + if (_grid.ColumnDefinitions[GetValue(Grid.ColumnProperty)].Width.IsAuto) + { + Orientation = Perspex.Controls.Orientation.Vertical; + return; + } + if (_grid.RowDefinitions[GetValue(Grid.RowProperty)].Height.IsAuto) + { + Orientation = Perspex.Controls.Orientation.Horizontal; + return; + } + throw new InvalidOperationException("GridSpliter Should have Orientation, width or height set."); } - public override Cursor Cursor => new Cursor(StandardCursorType.SizeNorthSouth); - - protected override double GetActualLength(RowDefinition definition) + private double GetActualLength(DefinitionBase definition) { - return definition.ActualHeight; + var columnDefinition = definition as ColumnDefinition; + return columnDefinition?.ActualWidth ?? ((RowDefinition)definition).ActualHeight; } - protected override double GetMaxLength(RowDefinition definition) + private double GetMinLength(DefinitionBase definition) { - return definition.MaxHeight; + var columnDefinition = definition as ColumnDefinition; + return columnDefinition?.MinWidth ?? ((RowDefinition)definition).MinHeight; } - protected override double GetMinLength(RowDefinition definition) + private double GetMaxLength(DefinitionBase definition) { - return definition.MinHeight; + var columnDefinition = definition as ColumnDefinition; + return columnDefinition?.MaxWidth ?? ((RowDefinition)definition).MaxHeight; } - protected override bool IsStar(RowDefinition definition) + private bool IsStar(DefinitionBase definition) { - return definition.Height.IsStar; + var columnDefinition = definition as ColumnDefinition; + return columnDefinition?.Width.IsStar ?? ((RowDefinition)definition).Height.IsStar; } - protected override double GetDelta(VectorEventArgs vectorEventArgs) + private void SetLengthInStars(DefinitionBase definition, double value) { - return vectorEventArgs.Vector.Y; + var columnDefinition = definition as ColumnDefinition; + if (columnDefinition != null) + { + columnDefinition.Width = new GridLength(value, GridUnitType.Star); + } + else + { + ((RowDefinition)definition).Height = new GridLength(value, GridUnitType.Star); + } } - protected override void SetLengthInStars(RowDefinition definition, double value) + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { - definition.Height = new GridLength(value, GridUnitType.Star); + base.OnAttachedToVisualTree(e); + _grid = this.GetVisualParent(); + AutoSetOrientation(); + if (Orientation.Value == Perspex.Controls.Orientation.Vertical) + { + Cursor = new Cursor(StandardCursorType.SizeWestEast); + var col = GetValue(Grid.ColumnProperty); + _definitions = _grid.ColumnDefinitions.Cast().ToList(); + _prevDefinition = _definitions[col - 1]; + _nextDefinition = _definitions[col + 1]; + } + else + { + Cursor = new Cursor(StandardCursorType.SizeNorthSouth); + var row = GetValue(Grid.RowProperty); + _definitions = _grid.RowDefinitions.Cast().ToList(); + _prevDefinition = _definitions[row - 1]; + _nextDefinition = _definitions[row + 1]; + } } } +} - internal class VerticalColumnsResizer : GridColumnsResizer - { - public VerticalColumnsResizer(Grid _grid, int splitterColumn) - { - _definitions = _grid.ColumnDefinitions; - _nextDefinition = _definitions[splitterColumn + 1]; - _prevDefinition = _definitions[splitterColumn - 1]; - } - - public override Cursor Cursor => new Cursor(StandardCursorType.SizeWestEast); - - protected override double GetActualLength(ColumnDefinition definition) - { - return definition.ActualWidth; - } - - protected override double GetMaxLength(ColumnDefinition definition) - { - return definition.MaxWidth; - } - - protected override double GetMinLength(ColumnDefinition definition) - { - return definition.MinWidth; - } - - protected override bool IsStar(ColumnDefinition definition) - { - return definition.Width.IsStar; - } - - protected override double GetDelta(VectorEventArgs vectorEventArgs) - { - return vectorEventArgs.Vector.X; - } - - protected override void SetLengthInStars(ColumnDefinition definition, double value) - { - definition.Width = new GridLength(value, GridUnitType.Star); - } - } -} \ No newline at end of file