Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Border issue #343 #352

Merged
merged 4 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading