Skip to content

Commit

Permalink
Merge pull request #352 from OlivierMiracle/border-issue-#343
Browse files Browse the repository at this point in the history
Border issue #343
  • Loading branch information
wieslawsoltes authored Sep 23, 2024
2 parents 2e0d2fb + 4007ce3 commit 8853274
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 94 deletions.
58 changes: 44 additions & 14 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 = Math.Max(0, (constraint.Width - splitterThickness) * proportion);
var width = CalculateDimension(constraint.Width - splitterThickness, proportion,
ref sumOfFractions);
var size = constraint.WithWidth(width);
control.Measure(size);
break;
}
case Orientation.Vertical:
{
var height = Math.Max(0, (constraint.Height - splitterThickness) * proportion);
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 += Math.Max(0, (constraint.Width - splitterThickness) * proportion);
usedWidth += CalculateDimension(constraint.Width - splitterThickness, proportion,
ref sumOfFractions);
}

break;
Expand All @@ -314,7 +319,8 @@ protected override Size MeasureOverride(Size constraint)
}
else
{
usedHeight += Math.Max(0, (constraint.Height - splitterThickness) * proportion);
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,8 @@ protected override Size ArrangeOverride(Size arrangeSize)
else
{
Debug.Assert(!double.IsNaN(proportion));
var width = Math.Max(0, (arrangeSize.Width - splitterThickness) * proportion);
var width = CalculateDimension(arrangeSize.Width - splitterThickness, proportion,
ref sumOfFractions);
remainingRect = remainingRect.WithWidth(width);
left += width;
}
Expand All @@ -414,7 +422,8 @@ protected override Size ArrangeOverride(Size arrangeSize)
else
{
Debug.Assert(!double.IsNaN(proportion));
var height = Math.Max(0, (arrangeSize.Height - splitterThickness) * proportion);
var height = CalculateDimension(arrangeSize.Height - splitterThickness, proportion,
ref sumOfFractions);
remainingRect = remainingRect.WithHeight(height);
top += height;
}
Expand All @@ -431,6 +440,27 @@ protected override Size ArrangeOverride(Size arrangeSize)
return arrangeSize;
}

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

// 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)
{
sumOfFractions -= Math.Round(sumOfFractions);
return Math.Max(0, flooredChildDimension + 1);
}

return Math.Max(0, flooredChildDimension);
}

/// <inheritdoc/>
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
Expand Down
Loading

0 comments on commit 8853274

Please sign in to comment.