Skip to content

Commit

Permalink
rewrite the command function to sum up the fractions of the pixels
Browse files Browse the repository at this point in the history
  • Loading branch information
OlivierMiracle committed Aug 15, 2024
1 parent d454fe1 commit a6d9f10
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 28 deletions.
60 changes: 36 additions & 24 deletions src/Dock.Avalonia/Controls/ProportionalStackPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Linq;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Data;
using Avalonia.Layout;

Expand Down Expand Up @@ -33,7 +32,8 @@ public Orientation Orientation
/// Defines the Proportion attached property.
/// </summary>
public static readonly AttachedProperty<double> ProportionProperty =
AvaloniaProperty.RegisterAttached<ProportionalStackPanel, Control, double>("Proportion", double.NaN, false, BindingMode.TwoWay);
AvaloniaProperty.RegisterAttached<ProportionalStackPanel, Control, double>("Proportion", double.NaN, false,
BindingMode.TwoWay);

/// <summary>
/// Gets the value of the Proportion attached property on the specified control.
Expand All @@ -59,7 +59,8 @@ public static void SetProportion(AvaloniaObject control, double value)
/// Defines the IsCollapsed attached property.
/// </summary>
public static readonly AttachedProperty<bool> IsCollapsedProperty =
AvaloniaProperty.RegisterAttached<ProportionalStackPanel, Control, bool>("IsCollapsed", false, false, BindingMode.TwoWay);
AvaloniaProperty.RegisterAttached<ProportionalStackPanel, Control, bool>("IsCollapsed", false, false,
BindingMode.TwoWay);

/// <summary>
/// Gets the value of the IsCollapsed attached property on the specified control.
Expand Down Expand Up @@ -191,7 +192,7 @@ private double GetTotalSplitterThickness(global::Avalonia.Controls.Controls chil
continue;
}
}

var thickness = proportionalStackPanelSplitter.Thickness;
totalThickness += thickness;
}
Expand All @@ -209,11 +210,11 @@ protected override Size MeasureOverride(Size constraint)
{
var horizontal = Orientation == Orientation.Horizontal;

if (constraint == Size.Infinity
|| (horizontal && double.IsInfinity(constraint.Width))
if (constraint == Size.Infinity
|| (horizontal && double.IsInfinity(constraint.Width))
|| (!horizontal && double.IsInfinity(constraint.Height)))
{
throw new Exception("Proportional StackPanel cannot be inside a control that offers infinite space.");
throw new Exception("Proportional StackPanel cannot be inside a control that offers infinite space.");
}

var usedWidth = 0.0;
Expand All @@ -225,7 +226,8 @@ protected override Size MeasureOverride(Size constraint)
AssignProportions(Children);

var needsNextSplitter = false;

double sumOfFractions = 0;

// Measure each of the Children
for (var i = 0; i < Children.Count; i++)
{
Expand Down Expand Up @@ -255,14 +257,16 @@ protected override Size MeasureOverride(Size constraint)
{
case Orientation.Horizontal:
{
var width = CalculateDimension(constraint.Width - splitterThickness, proportion, i);
var width = CalculateDimension(constraint.Width - splitterThickness, proportion,
ref sumOfFractions);
var size = constraint.WithWidth(width);
control.Measure(size);
break;
}
case Orientation.Vertical:
{
var height = CalculateDimension(constraint.Height - splitterThickness, proportion, i);
var height = CalculateDimension(constraint.Height - splitterThickness, proportion,
ref sumOfFractions);
var size = constraint.WithHeight(height);
control.Measure(size);
break;
Expand Down Expand Up @@ -299,7 +303,8 @@ protected override Size MeasureOverride(Size constraint)
}
else
{
usedWidth += CalculateDimension(constraint.Width - splitterThickness, proportion, i);
usedWidth += CalculateDimension(constraint.Width - splitterThickness, proportion,
ref sumOfFractions);
}

break;
Expand All @@ -314,7 +319,8 @@ protected override Size MeasureOverride(Size constraint)
}
else
{
usedHeight += CalculateDimension(constraint.Height - splitterThickness, proportion, i);
usedHeight += CalculateDimension(constraint.Height - splitterThickness, proportion,
ref sumOfFractions);
}

break;
Expand Down Expand Up @@ -343,6 +349,7 @@ protected override Size ArrangeOverride(Size arrangeSize)
AssignProportions(Children);

var needsNextSplitter = false;
double sumOfFractions = 0;

for (var i = 0; i < Children.Count; i++)
{
Expand Down Expand Up @@ -397,7 +404,7 @@ protected override Size ArrangeOverride(Size arrangeSize)
else
{
Debug.Assert(!double.IsNaN(proportion));
var width = CalculateDimension(arrangeSize.Width - splitterThickness, proportion, i);
var width = CalculateDimension(arrangeSize.Width - splitterThickness, proportion, ref sumOfFractions);
remainingRect = remainingRect.WithWidth(width);
left += width;
}
Expand All @@ -414,7 +421,7 @@ protected override Size ArrangeOverride(Size arrangeSize)
else
{
Debug.Assert(!double.IsNaN(proportion));
var height = CalculateDimension(arrangeSize.Height - splitterThickness, proportion, i);
var height = CalculateDimension(arrangeSize.Height - splitterThickness, proportion, ref sumOfFractions);
remainingRect = remainingRect.WithHeight(height);
top += height;
}
Expand All @@ -430,21 +437,26 @@ protected override Size ArrangeOverride(Size arrangeSize)

return arrangeSize;
}

private double CalculateDimension(double dimension, double proportion, int childIndex)

private double CalculateDimension(
double dimension,
double proportion,
ref double sumOfFractions)
{
var childDimension = dimension * proportion;
var flooredChildDimension = Math.Floor(childDimension);

// checks whether division doesn't leave a fraction
if (childDimension == flooredChildDimension)
return Math.Max(0, flooredChildDimension);
else

// sums fractions from the division
sumOfFractions += childDimension - flooredChildDimension;

// if the sum of fractions made up a whole pixel/pixels, add it to the dimension
if (Math.Round(sumOfFractions, 1) - Math.Clamp(Math.Floor(sumOfFractions), 1, double.MaxValue) >= 0)
{
// if it leaves, it assigns the divided pixel to the first control in proportional split
int isFirst = childIndex == 0 ? 1 : 0;
return Math.Max(0, flooredChildDimension + isFirst);
sumOfFractions -= Math.Round(sumOfFractions);
return Math.Max(0, flooredChildDimension + 1);
}

return Math.Max(0, flooredChildDimension);
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private static IEnumerable<object[]> GetBorderTestsData()
yield return [0.5, 604, 300, 300];
yield return [0.25, 604, 150, 450];
yield return [0.6283185307179586476925286766559, 604, 377, 223];
yield return [0.3141592653589793238462643383279, 604, 189, 411];
yield return [0.3141592653589793238462643383279, 604, 188, 412];
}

[Theory]
Expand Down Expand Up @@ -187,10 +187,11 @@ public void Lays_Out_Children_Default()
target.Measure(Size.Infinity);
target.Arrange(new Rect(target.DesiredSize));

// values have to add up to width/height of the parent control
Assert.Equal(new Size(1000, 500), target.Bounds.Size);
Assert.Equal(new Rect(0, 0, 331, 500), target.Children[0].Bounds);
Assert.Equal(new Rect(331, 0, 4, 500), target.Children[1].Bounds);
Assert.Equal(new Rect(335, 0, 331, 500), target.Children[2].Bounds);
Assert.Equal(new Rect(0, 0, 330, 500), target.Children[0].Bounds);
Assert.Equal(new Rect(330, 0, 4, 500), target.Children[1].Bounds);
Assert.Equal(new Rect(334, 0, 331, 500), target.Children[2].Bounds);
Assert.Equal(new Rect(665, 0, 4, 500), target.Children[3].Bounds);
Assert.Equal(new Rect(669, 0, 331, 500), target.Children[4].Bounds);
}
Expand Down

0 comments on commit a6d9f10

Please sign in to comment.