diff --git a/TUI.Test/StackPanelTests.cs b/TUI.Test/StackPanelTests.cs
index b6d436a..b08469a 100644
--- a/TUI.Test/StackPanelTests.cs
+++ b/TUI.Test/StackPanelTests.cs
@@ -510,11 +510,64 @@ public void StackPanelVerticalMeasuresWidthIndependentElementsAtTheirOwnSize()
FixedSizeElementBase derived = new() { Dimensions = new Dimensions(4, 3) };
Assert.AreEqual(direct.Size, ((IUIElement)direct).CalculateRequiredDimensions(1));
- Assert.AreEqual(new Dimensions(3, 2), direct.Dimensions);
+ // The height is the measured one; the width spans the panel (ktsu-dev/TUI#158)
+ Assert.AreEqual(new Dimensions(10, 2), direct.Dimensions);
Assert.AreEqual(new Position(0, 2), next.Position);
Assert.AreEqual(derived.CalculateRequiredDimensions(), derived.CalculateRequiredDimensions(1));
}
+ ///
+ /// A vertical stack gives each child the panel's full width, so a centered or right-aligned
+ /// child has room to align in (ktsu-dev/TUI#158).
+ ///
+ /// The horizontal alignment under test.
+ /// The column the text should be written at.
+ [TestMethod]
+ [DataRow(HorizontalAlignment.Left, 0)]
+ [DataRow(HorizontalAlignment.Center, 19)]
+ [DataRow(HorizontalAlignment.Right, 38)]
+ public void StackPanelVerticalChildAlignsWithinThePanelWidth(HorizontalAlignment alignment, int expectedX)
+ {
+ // Arrange
+ TextElement text = new("hi") { HorizontalAlignment = alignment };
+ StackPanel panel = [text];
+ panel.Position = Position.Origin;
+ panel.Dimensions = new Dimensions(40, 10);
+ RecordingConsoleProvider provider = new();
+
+ // Act
+ panel.ArrangeChildren();
+ panel.Render(provider);
+
+ // Assert
+ Assert.AreEqual(new Dimensions(40, 1), text.Dimensions);
+ Assert.AreEqual(expectedX, provider.WritesOf("hi").Single().Position.X);
+ }
+
+ ///
+ /// A horizontal stack gives each child the panel's full height and keeps the measured width on
+ /// the stacking axis, so the stacking offsets do not change (ktsu-dev/TUI#158).
+ ///
+ [TestMethod]
+ public void StackPanelHorizontalChildSpansThePanelHeight()
+ {
+ // Arrange
+ TextElement first = new("abc");
+ TextElement second = new("de");
+ StackPanel panel = new(Orientation.Horizontal) { Spacing = 1 };
+ panel.AddChild(first);
+ panel.AddChild(second);
+ panel.Dimensions = new Dimensions(20, 5);
+
+ // Act
+ panel.ArrangeChildren();
+
+ // Assert
+ Assert.AreEqual(new Dimensions(3, 5), first.Dimensions);
+ Assert.AreEqual(new Dimensions(2, 5), second.Dimensions);
+ Assert.AreEqual(new Position(4, 0), second.Position);
+ }
+
///
/// Tests that a container that does not use the available width, such as BorderElement, measures
/// the same with or without one.
diff --git a/TUI.Test/UIApplicationResizeTests.cs b/TUI.Test/UIApplicationResizeTests.cs
index 3e23878..e76d27f 100644
--- a/TUI.Test/UIApplicationResizeTests.cs
+++ b/TUI.Test/UIApplicationResizeTests.cs
@@ -90,7 +90,7 @@ public void RenderAfterAResizeRelaysOutEveryContainerBeneathTheRoot()
UIApplication app = new(provider) { RootElement = root };
app.Render();
Assert.AreEqual(LaunchSize.WithoutPadding(root.Padding), panel.Dimensions, "The panel should start out filling the terminal, inside the border");
- Assert.AreEqual(WideText.Length, leaf.Dimensions.Width, "The label should start out at its full width");
+ Assert.AreEqual(panel.Dimensions.Width, leaf.Dimensions.Width, "The label should start out spanning the panel");
// Act
provider.Dimensions = ResizedSize;
diff --git a/TUI/Elements/Layouts/StackPanel.cs b/TUI/Elements/Layouts/StackPanel.cs
index d1858f8..321c565 100644
--- a/TUI/Elements/Layouts/StackPanel.cs
+++ b/TUI/Elements/Layouts/StackPanel.cs
@@ -99,10 +99,11 @@ protected override void OnArrangeChildren()
if (Orientation == Orientation.Vertical)
{
- // Vertical stacking
+ // Vertical stacking. The child spans the panel's width rather than its own measured
+ // width, so it has room to apply its own horizontal alignment (ktsu-dev/TUI#158).
child.Position = contentPosition.Offset(0, currentOffset);
child.Dimensions = new Dimensions(
- Math.Min(childDimensions.Width, contentArea.Width),
+ contentArea.Width,
Math.Min(childDimensions.Height, contentArea.Height - currentOffset)
);
@@ -116,11 +117,11 @@ protected override void OnArrangeChildren()
}
else
{
- // Horizontal stacking
+ // Horizontal stacking. The child spans the panel's height, matching the vertical case.
child.Position = contentPosition.Offset(currentOffset, 0);
child.Dimensions = new Dimensions(
Math.Min(childDimensions.Width, contentArea.Width - currentOffset),
- Math.Min(childDimensions.Height, contentArea.Height)
+ contentArea.Height
);
currentOffset += child.Dimensions.Width + Spacing;