From 6431b765a13c4bba927e6acd360ca7daed66b4c5 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Wed, 23 Apr 2025 15:23:46 -0400 Subject: [PATCH] Pick nearest parent if container query doesn't specify container name (#18707) * pick nearest parent if container query doesn't specify container name * add to string overrides for queries --- .../Activators/ContainerQueryActivatorBase.cs | 3 +- src/Avalonia.Base/Styling/ScreenQueries.cs | 32 +++++++++++++---- .../Styling/ContainerTests.cs | 36 +++++++++++-------- 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/Avalonia.Base/Styling/Activators/ContainerQueryActivatorBase.cs b/src/Avalonia.Base/Styling/Activators/ContainerQueryActivatorBase.cs index 932fab488d..c9223ce068 100644 --- a/src/Avalonia.Base/Styling/Activators/ContainerQueryActivatorBase.cs +++ b/src/Avalonia.Base/Styling/Activators/ContainerQueryActivatorBase.cs @@ -74,7 +74,8 @@ namespace Avalonia.Styling.Activators internal static Layoutable? GetContainer(Visual visual, string? containerName) { return visual.GetVisualAncestors().Where(x => x is Layoutable layoutable && - (Container.GetName(layoutable) == containerName)).FirstOrDefault() as Layoutable; + ((containerName == null && Container.GetSizing(layoutable) != ContainerSizing.Normal) + || (containerName != null && Container.GetName(layoutable) == containerName))).FirstOrDefault() as Layoutable; } private void HeightChanged(object? sender, EventArgs e) diff --git a/src/Avalonia.Base/Styling/ScreenQueries.cs b/src/Avalonia.Base/Styling/ScreenQueries.cs index 2c102768dd..e82879fd7e 100644 --- a/src/Avalonia.Base/Styling/ScreenQueries.cs +++ b/src/Avalonia.Base/Styling/ScreenQueries.cs @@ -67,11 +67,22 @@ namespace Avalonia.Styling SelectorMatch.AlwaysThisInstance : SelectorMatch.NeverThisInstance; } - public override string ToString() => "width"; + public override string ToString() => ToString(null); public override string ToString(ContainerQuery? owner) { - throw new NotImplementedException(); + var prop = Argument.@operator switch + { + StyleQueryComparisonOperator.None => "", + StyleQueryComparisonOperator.Equals => "width", + StyleQueryComparisonOperator.LessThan => "", + StyleQueryComparisonOperator.GreaterThan => "", + StyleQueryComparisonOperator.LessThanOrEquals => "max-width", + StyleQueryComparisonOperator.GreaterThanOrEquals => "min-width", + _ => throw new NotImplementedException(), + }; + + return $"{prop}:{Argument.value}"; } } @@ -112,8 +123,6 @@ namespace Avalonia.Styling return SelectorMatch.NeverThisInstance; } - var isvalueTrue = IsTrue(argument.@operator, argument.value); - bool IsTrue(StyleQueryComparisonOperator comparisonOperator, double value) { switch (comparisonOperator) @@ -139,11 +148,22 @@ namespace Avalonia.Styling SelectorMatch.AlwaysThisInstance : SelectorMatch.NeverThisInstance; } - public override string ToString() => "height"; + public override string ToString() => ToString(null); public override string ToString(ContainerQuery? owner) { - throw new NotImplementedException(); + var prop = Argument.@operator switch + { + StyleQueryComparisonOperator.None => "", + StyleQueryComparisonOperator.Equals => "height", + StyleQueryComparisonOperator.LessThan => "", + StyleQueryComparisonOperator.GreaterThan => "", + StyleQueryComparisonOperator.LessThanOrEquals => "max-height", + StyleQueryComparisonOperator.GreaterThanOrEquals => "min-height", + _ => throw new NotImplementedException(), + }; + + return $"{prop}:{Argument.value}"; } } } diff --git a/tests/Avalonia.Base.UnitTests/Styling/ContainerTests.cs b/tests/Avalonia.Base.UnitTests/Styling/ContainerTests.cs index a8cb137dcc..a46e494b9d 100644 --- a/tests/Avalonia.Base.UnitTests/Styling/ContainerTests.cs +++ b/tests/Avalonia.Base.UnitTests/Styling/ContainerTests.cs @@ -30,7 +30,7 @@ namespace Avalonia.Base.UnitTests.Styling containerQuery1.Children.Add(new Style(x => x.Is()) { Setters = { new Setter(Control.WidthProperty, 200.0) } - }); + }); var containerQuery2 = new ContainerQuery(x => new WidthQuery(x, StyleQueryComparisonOperator.GreaterThan, 500)); containerQuery2.Children.Add(new Style(x => x.Is()) { @@ -43,11 +43,13 @@ namespace Avalonia.Base.UnitTests.Styling Name = "Child", HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch }; + var stack = new StackPanel(); + stack.Children.Add(child); var border = new Border() { HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Stretch, - Child = child, + Child = stack, Name = "Parent" }; Container.SetSizing(border, Avalonia.Styling.ContainerSizing.Width); @@ -55,13 +57,13 @@ namespace Avalonia.Base.UnitTests.Styling root.Child = border; root.LayoutManager.ExecuteInitialLayoutPass(); - Assert.Equal(child.Width, 200.0); + Assert.Equal(200, child.Width); root.ClientSize = new Size(600, 600); root.InvalidateMeasure(); root.LayoutManager.ExecuteLayoutPass(); - Assert.Equal(child.Width, 500.0); + Assert.Equal(500, child.Width); } [Fact] @@ -89,11 +91,13 @@ namespace Avalonia.Base.UnitTests.Styling Name = "Child", VerticalAlignment = Avalonia.Layout.VerticalAlignment.Stretch }; + var stack = new StackPanel(); + stack.Children.Add(child); var border = new Border() { HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Stretch, - Child = child, + Child = stack, Name = "Parent" }; Container.SetSizing(border, Avalonia.Styling.ContainerSizing.Height); @@ -101,13 +105,13 @@ namespace Avalonia.Base.UnitTests.Styling root.Child = border; root.LayoutManager.ExecuteInitialLayoutPass(); - Assert.Equal(child.Height, 200.0); + Assert.Equal(200, child.Height); root.ClientSize = new Size(600, 600); root.InvalidateMeasure(); root.LayoutManager.ExecuteLayoutPass(); - Assert.Equal(child.Height, 500.0); + Assert.Equal(500, child.Height); } [Fact] @@ -128,8 +132,8 @@ namespace Avalonia.Base.UnitTests.Styling { Setters = { new Setter(Control.WidthProperty, 300.0) } }); - root.Styles.Add(containerQuery2); root.Styles.Add(containerQuery1); + root.Styles.Add(containerQuery2); var child = new Border() { Name = "Child", @@ -144,11 +148,13 @@ namespace Avalonia.Base.UnitTests.Styling }; Container.SetSizing(controlInner, Avalonia.Styling.ContainerSizing.Width); Container.SetName(controlInner, "TEST"); + var stack = new StackPanel(); + stack.Children.Add(controlInner); var border = new Border() { HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Stretch, - Child = controlInner, + Child = stack, Name = "Parent" }; Container.SetSizing(border, Avalonia.Styling.ContainerSizing.Width); @@ -158,7 +164,7 @@ namespace Avalonia.Base.UnitTests.Styling root.LayoutManager.ExecuteInitialLayoutPass(); root.LayoutManager.ExecuteLayoutPass(); - Assert.Equal(child.Width, 300.0); + Assert.Equal(300, child.Width); } [Fact] @@ -174,13 +180,13 @@ namespace Avalonia.Base.UnitTests.Styling { Setters = { new Setter(Control.HeightProperty, 200.0) } }); - var containerQuery2 = new ContainerQuery(x => new HeightQuery(x, StyleQueryComparisonOperator.LessThanOrEquals, 500), "TEST"); + var containerQuery2 = new ContainerQuery(x => new HeightQuery(x, StyleQueryComparisonOperator.LessThanOrEquals, 450), "TEST"); containerQuery2.Children.Add(new Style(x => x.Is()) { Setters = { new Setter(Control.HeightProperty, 300.0) } }); - root.Styles.Add(containerQuery2); root.Styles.Add(containerQuery1); + root.Styles.Add(containerQuery2); var child = new Border() { Name = "Child", @@ -195,11 +201,13 @@ namespace Avalonia.Base.UnitTests.Styling }; Container.SetSizing(controlInner, Avalonia.Styling.ContainerSizing.Height); Container.SetName(controlInner, "TEST"); + var stack = new StackPanel(); + stack.Children.Add(controlInner); var border = new Border() { HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Stretch, - Child = controlInner, + Child = stack, Name = "Parent" }; Container.SetSizing(border, Avalonia.Styling.ContainerSizing.Height); @@ -209,7 +217,7 @@ namespace Avalonia.Base.UnitTests.Styling root.LayoutManager.ExecuteInitialLayoutPass(); root.LayoutManager.ExecuteLayoutPass(); - Assert.Equal(child.Height, 300.0); + Assert.Equal(300, child.Height); } } }