Skip to content

Commit

Permalink
Fixes CommunityToolkit#3949 - SizerBase, GridSplitter, and ContentSiz…
Browse files Browse the repository at this point in the history
…er all use Cumulative change to update sizes vs. Delta

This fixes long-standing issue where mouse would de-sync from gripper bar and provide a disorienting experience to users. Now the bar only moves when the mouse is over it and ignores extra movement - the same as Thumb controls do within a Slider for instance.
  • Loading branch information
michael-hawker committed Mar 5, 2022
1 parent 2e8e739 commit 859987f
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ protected override void OnLoaded(RoutedEventArgs e)
{
// TODO: Make Converter to put in XAML?
Content =
Orientation == Orientation.Vertical ? GripperBarVertical : GripperBarHorizontal;
Orientation == Orientation.Vertical ?
GripperBarVertical :
GripperBarHorizontal;
}

if (TargetControl == null)
Expand All @@ -33,8 +35,22 @@ protected override void OnLoaded(RoutedEventArgs e)
}
}

private double _currentSize;

/// <inheritdoc/>
protected override void OnDragStarting()
{
if (TargetControl != null)
{
_currentSize =
Orientation == Orientation.Vertical ?
TargetControl.ActualWidth :
TargetControl.ActualHeight;
}
}

/// <inheritdoc/>
protected override bool OnHorizontalMove(double horizontalChange)
protected override bool OnDragHorizontal(double horizontalChange)
{
if (TargetControl == null)
{
Expand All @@ -43,39 +59,38 @@ protected override bool OnHorizontalMove(double horizontalChange)

horizontalChange = IsDragInverted ? -horizontalChange : horizontalChange;

if (!IsValidWidth(TargetControl, horizontalChange, ActualWidth))
if (!IsValidWidth(TargetControl, _currentSize + horizontalChange, ActualWidth))
{
return true;
return false;
}

TargetControl.Width += horizontalChange;
TargetControl.Width = _currentSize + horizontalChange;

GripperCursor = CoreCursorType.SizeWestEast;

return false;
return true;
}

/// <inheritdoc/>
protected override bool OnVerticalMove(double verticalChange)
protected override bool OnDragVertical(double verticalChange)
{
if (TargetControl == null)
{
return true;
return false;
}

verticalChange = IsDragInverted ? -verticalChange : verticalChange;

if (!IsValidHeight(TargetControl, verticalChange, ActualHeight))
if (!IsValidHeight(TargetControl, _currentSize + verticalChange, ActualHeight))
{
return true;
return false;
}

// Do we need our ContentResizeDirection to be 4 way? Maybe 'Auto' would check the horizontal/vertical alignment of the target???
TargetControl.Height += verticalChange;
TargetControl.Height = _currentSize + verticalChange;

GripperCursor = CoreCursorType.SizeNorthSouth;

return false;
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,48 +33,58 @@ protected override void OnLoaded(RoutedEventArgs e)
GripperCursor = _resizeDirection == GridResizeDirection.Columns ? CoreCursorType.SizeWestEast : CoreCursorType.SizeNorthSouth;
}

private double _currentSize;
private double _siblingSize;

/// <inheritdoc />
protected override void OnManipulationStarted(ManipulationStartedRoutedEventArgs e)
protected override void OnDragStarting()
{
_resizeDirection = GetResizeDirection();
Orientation = _resizeDirection == GridResizeDirection.Rows ?
Orientation.Horizontal : Orientation.Vertical;
_resizeBehavior = GetResizeBehavior();

base.OnManipulationStarted(e);
// Record starting points
if (Orientation == Orientation.Horizontal)
{
_currentSize = CurrentRow?.ActualHeight ?? -1;
_siblingSize = SiblingRow?.ActualHeight ?? -1;
}
else
{
_currentSize = CurrentColumn?.ActualWidth ?? -1;
_siblingSize = SiblingColumn?.ActualWidth ?? -1;
}
}

/// <inheritdoc/>
protected override bool OnVerticalMove(double verticalChange)
protected override bool OnDragVertical(double verticalChange)
{
if (CurrentRow == null || SiblingRow == null)
{
return true;
return false;
}

var currentChange = _currentSize + verticalChange;
var siblingChange = _siblingSize + (verticalChange * -1); // sibling moves opposite

// if current row has fixed height then resize it
if (!IsStarRow(CurrentRow))
{
// No need to check for the row Min height because it is automatically respected
if (!SetRowHeight(CurrentRow, verticalChange, GridUnitType.Pixel))
{
return true;
}
return SetRowHeight(CurrentRow, currentChange, GridUnitType.Pixel);
}

// if sibling row has fixed width then resize it
else if (!IsStarRow(SiblingRow))
{
// Would adding to this column make the current column violate the MinWidth?
if (IsValidRowHeight(CurrentRow, verticalChange) == false)
if (IsValidRowHeight(CurrentRow, currentChange) == false)
{
return false;
}

if (!SetRowHeight(SiblingRow, verticalChange * -1, GridUnitType.Pixel))
{
return true;
}
return SetRowHeight(SiblingRow, siblingChange, GridUnitType.Pixel);
}

// if both row haven't fixed height (auto *)
Expand All @@ -85,63 +95,60 @@ protected override bool OnVerticalMove(double verticalChange)
// respect the other star row height by setting it's height to it's actual height with stars

// We need to validate current and sibling height to not cause any unexpected behavior
if (!IsValidRowHeight(CurrentRow, verticalChange) ||
!IsValidRowHeight(SiblingRow, verticalChange * -1))
if (!IsValidRowHeight(CurrentRow, currentChange) ||
!IsValidRowHeight(SiblingRow, siblingChange))
{
return true;
return false;
}

foreach (var rowDefinition in Resizable.RowDefinitions)
{
if (rowDefinition == CurrentRow)
{
SetRowHeight(CurrentRow, verticalChange, GridUnitType.Star);
SetRowHeight(CurrentRow, currentChange, GridUnitType.Star);
}
else if (rowDefinition == SiblingRow)
{
SetRowHeight(SiblingRow, verticalChange * -1, GridUnitType.Star);
SetRowHeight(SiblingRow, siblingChange, GridUnitType.Star);
}
else if (IsStarRow(rowDefinition))
{
rowDefinition.Height = new GridLength(rowDefinition.ActualHeight, GridUnitType.Star);
}
}
}

return false;
return true;
}
}

/// <inheritdoc/>
protected override bool OnHorizontalMove(double horizontalChange)
protected override bool OnDragHorizontal(double horizontalChange)
{
if (CurrentColumn == null || SiblingColumn == null)
{
return true;
return false;
}

var currentChange = _currentSize + horizontalChange;
var siblingChange = _siblingSize + (horizontalChange * -1); // sibling moves opposite

// if current column has fixed width then resize it
if (!IsStarColumn(CurrentColumn))
{
// No need to check for the Column Min width because it is automatically respected
if (!SetColumnWidth(CurrentColumn, horizontalChange, GridUnitType.Pixel))
{
return true;
}
return SetColumnWidth(CurrentColumn, currentChange, GridUnitType.Pixel);
}

// if sibling column has fixed width then resize it
else if (!IsStarColumn(SiblingColumn))
{
// Would adding to this column make the current column violate the MinWidth?
if (IsValidColumnWidth(CurrentColumn, horizontalChange) == false)
if (IsValidColumnWidth(CurrentColumn, currentChange) == false)
{
return false;
}

if (!SetColumnWidth(SiblingColumn, horizontalChange * -1, GridUnitType.Pixel))
{
return true;
}
return SetColumnWidth(SiblingColumn, siblingChange, GridUnitType.Pixel);
}

// if both column haven't fixed width (auto *)
Expand All @@ -152,30 +159,30 @@ protected override bool OnHorizontalMove(double horizontalChange)
// respect the other star column width by setting it's width to it's actual width with stars

// We need to validate current and sibling width to not cause any unexpected behavior
if (!IsValidColumnWidth(CurrentColumn, horizontalChange) ||
!IsValidColumnWidth(SiblingColumn, horizontalChange * -1))
if (!IsValidColumnWidth(CurrentColumn, currentChange) ||
!IsValidColumnWidth(SiblingColumn, siblingChange))
{
return true;
return false;
}

foreach (var columnDefinition in Resizable.ColumnDefinitions)
{
if (columnDefinition == CurrentColumn)
{
SetColumnWidth(CurrentColumn, horizontalChange, GridUnitType.Star);
SetColumnWidth(CurrentColumn, currentChange, GridUnitType.Star);
}
else if (columnDefinition == SiblingColumn)
{
SetColumnWidth(SiblingColumn, horizontalChange * -1, GridUnitType.Star);
SetColumnWidth(SiblingColumn, siblingChange, GridUnitType.Star);
}
else if (IsStarColumn(columnDefinition))
{
columnDefinition.Width = new GridLength(columnDefinition.ActualWidth, GridUnitType.Star);
}
}
}

return false;
return true;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ private static bool IsStarRow(RowDefinition definition)
return ((GridLength)definition.GetValue(RowDefinition.HeightProperty)).IsStar;
}

private bool SetColumnWidth(ColumnDefinition columnDefinition, double horizontalChange, GridUnitType unitType)
private bool SetColumnWidth(ColumnDefinition columnDefinition, double newWidth, GridUnitType unitType)
{
var newWidth = columnDefinition.ActualWidth + horizontalChange;

var minWidth = columnDefinition.MinWidth;
if (!double.IsNaN(minWidth) && newWidth < minWidth)
{
Expand All @@ -47,10 +45,8 @@ private bool SetColumnWidth(ColumnDefinition columnDefinition, double horizontal
return false;
}

private bool IsValidColumnWidth(ColumnDefinition columnDefinition, double horizontalChange)
private bool IsValidColumnWidth(ColumnDefinition columnDefinition, double newWidth)
{
var newWidth = columnDefinition.ActualWidth + horizontalChange;

var minWidth = columnDefinition.MinWidth;
if (!double.IsNaN(minWidth) && newWidth < minWidth)
{
Expand All @@ -71,10 +67,8 @@ private bool IsValidColumnWidth(ColumnDefinition columnDefinition, double horizo
return true;
}

private bool SetRowHeight(RowDefinition rowDefinition, double verticalChange, GridUnitType unitType)
private bool SetRowHeight(RowDefinition rowDefinition, double newHeight, GridUnitType unitType)
{
var newHeight = rowDefinition.ActualHeight + verticalChange;

var minHeight = rowDefinition.MinHeight;
if (!double.IsNaN(minHeight) && newHeight < minHeight)
{
Expand All @@ -96,10 +90,8 @@ private bool SetRowHeight(RowDefinition rowDefinition, double verticalChange, Gr
return false;
}

private bool IsValidRowHeight(RowDefinition rowDefinition, double verticalChange)
private bool IsValidRowHeight(RowDefinition rowDefinition, double newHeight)
{
var newHeight = rowDefinition.ActualHeight + verticalChange;

var minHeight = rowDefinition.MinHeight;
if (!double.IsNaN(minHeight) && newHeight < minHeight)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,39 @@ protected override void OnKeyDown(KeyRoutedEventArgs e)

if (e.Key == Windows.System.VirtualKey.Left)
{
OnHorizontalMove(-horizontalChange);
OnDragHorizontal(-horizontalChange);
}
else if (e.Key == Windows.System.VirtualKey.Right)
{
OnHorizontalMove(horizontalChange);
OnDragHorizontal(horizontalChange);
}
}
else
{
if (e.Key == Windows.System.VirtualKey.Up)
{
OnVerticalMove(-GripperKeyboardChange);
OnDragVertical(-GripperKeyboardChange);
}
else if (e.Key == Windows.System.VirtualKey.Down)
{
OnVerticalMove(GripperKeyboardChange);
OnDragVertical(GripperKeyboardChange);
}
}
}

/// <inheritdoc />
protected override void OnManipulationStarting(ManipulationStartingRoutedEventArgs e)
{
base.OnManipulationStarting(e);

OnDragStarting();
}

/// <inheritdoc />
protected override void OnManipulationDelta(ManipulationDeltaRoutedEventArgs e)
{
var horizontalChange = e.Delta.Translation.X;
var verticalChange = e.Delta.Translation.Y;
var horizontalChange = e.Cumulative.Translation.X;
var verticalChange = e.Cumulative.Translation.Y;

// Important: adjust for RTL language flow settings and invert horizontal axis
if (this.FlowDirection == FlowDirection.RightToLeft)
Expand All @@ -72,14 +80,14 @@ protected override void OnManipulationDelta(ManipulationDeltaRoutedEventArgs e)

if (Orientation == Orientation.Vertical)
{
if (OnHorizontalMove(horizontalChange))
if (!OnDragHorizontal(horizontalChange))
{
return;
}
}
else if (Orientation == Orientation.Horizontal)
{
if (OnVerticalMove(verticalChange))
if (!OnDragVertical(verticalChange))
{
return;
}
Expand Down
Loading

0 comments on commit 859987f

Please sign in to comment.