Skip to content

Commit

Permalink
Merge branch 'release/8.0.1xx-sr2' into main (#20371)
Browse files Browse the repository at this point in the history
- Fixes: #20126
  • Loading branch information
PureWeen committed Feb 6, 2024
2 parents a6c9997 + 291eb24 commit 96288c1
Show file tree
Hide file tree
Showing 6 changed files with 411 additions and 21 deletions.
51 changes: 41 additions & 10 deletions src/Controls/src/Core/Editor/Editor.cs
@@ -1,8 +1,10 @@
#nullable disable
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Graphics;
using static Microsoft.Maui.Primitives.Dimension;

namespace Microsoft.Maui.Controls
{
Expand Down Expand Up @@ -86,6 +88,10 @@ void UpdateAutoSizeOption()
public event EventHandler Completed;
double _previousWidthConstraint;
double _previousHeightConstraint;
double _previousWidthRequest;
double _previousHeightRequest;
Thickness _previousMargin;

Rect _previousBounds;

/// <include file="../../docs/Microsoft.Maui.Controls/Editor.xml" path="//Member[@MemberName='.ctor']/Docs/*" />
Expand Down Expand Up @@ -123,7 +129,7 @@ void IEditor.Completed()
{
(this as IEditorController).SendCompleted();
}

protected override Size ArrangeOverride(Rect bounds)
{
_previousBounds = bounds;
Expand All @@ -132,24 +138,49 @@ protected override Size ArrangeOverride(Rect bounds)

protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
{
if (AutoSize == EditorAutoSizeOption.Disabled &&
Width > 0 &&
Height > 0)
if (AutoSize == EditorAutoSizeOption.TextChanges)
{
if (TheSame(_previousHeightConstraint, heightConstraint) &&
TheSame(_previousWidthConstraint, widthConstraint))
return base.MeasureOverride(widthConstraint, heightConstraint);
}

IView view = this;
if (Width > 0 &&
Height > 0 &&
// If the user hasn't changed any of the WxH constraints then we don't want to remeasure
// We want the Editor to remain the same size
_previousWidthRequest == WidthRequest &&
_previousHeightRequest == HeightRequest &&
_previousMargin == Margin &&
// If the user has explicitly set the width and height we don't need to special case around AutoSize
// The explicitly set values will already stop any resizing from happening
(!IsExplicitSet(view.Width) || !IsExplicitSet(view.Height))
)
{
// check if the min/max constraints have changed and are no longer valid
if (IsExplicitSet(view.MinimumWidth) && Width < view.MinimumWidth ||
IsExplicitSet(view.MaximumWidth) && Width > view.MaximumWidth ||
IsExplicitSet(view.MinimumHeight) && Height < view.MinimumHeight ||
IsExplicitSet(view.MaximumHeight) && Height > view.MaximumHeight)
{
return new Size(Width, Height);
_previousWidthConstraint = -1;
_previousHeightConstraint = -1;
}
else if (TheSame(_previousHeightConstraint, _previousBounds.Height) &&
TheSame(_previousWidthConstraint, _previousBounds.Width))
else if ((TheSame(_previousHeightConstraint, heightConstraint) &&
TheSame(_previousWidthConstraint, widthConstraint)) ||
(TheSame(_previousHeightConstraint, _previousBounds.Height) &&
TheSame(_previousWidthConstraint, _previousBounds.Width)))
{
return new Size(Width, Height);
// Just return previously established desired size
return DesiredSize;
}
}

_previousWidthRequest = WidthRequest;
_previousHeightRequest = HeightRequest;
_previousMargin = Margin;
_previousWidthConstraint = widthConstraint;
_previousHeightConstraint = heightConstraint;

return base.MeasureOverride(widthConstraint, heightConstraint);

bool TheSame(double width, double otherWidth)
Expand Down
192 changes: 185 additions & 7 deletions src/Controls/tests/DeviceTests/Elements/Editor/EditorTests.cs
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
Expand Down Expand Up @@ -32,26 +33,29 @@ public async Task AutoSizeInitializesCorrectly(EditorAutoSizeOption option)
Text = "Test"
};

IView layout = new VerticalStackLayout()
var layout = new VerticalStackLayout()
{
WidthRequest = 100,
HeightRequest = 100,
Children =
{
editor
}
};

await CreateHandlerAndAddToWindow<LayoutHandler>(layout, async (_) =>
await AttachAndRun<LayoutHandler>(layout, async (_) =>
{
var frame = editor.Frame;
layout.Arrange(new Graphics.Rect(Graphics.Point.Zero, layout.Measure(100, 100)));
await WaitForUIUpdate(frame, editor);
await Task.Yield();
var initialHeight = editor.Height;
editor.Text += Environment.NewLine + " Some new text" + Environment.NewLine + " Some new text" + Environment.NewLine;
layout.Arrange(new Graphics.Rect(Graphics.Point.Zero, layout.Measure(1000, 1000)));
layout.WidthRequest = 1000;
layout.HeightRequest = 1000;
await WaitForUIUpdate(frame, editor);
if (option == EditorAutoSizeOption.TextChanges)
Expand All @@ -61,10 +65,184 @@ public async Task AutoSizeInitializesCorrectly(EditorAutoSizeOption option)
});
}

static async Task WaitForUIUpdate(Graphics.Rect frame, Editor collectionView, int timeout = 1000, int interval = 100)
[Fact]
public async Task EditorMeasureUpdatesWhenChangingHeight()
{
await ValidateEditorLayoutChangesForDisabledAutoSize(
null,
(control) => control.HeightRequest = 60,
(control) =>
{
var frame = control.Frame;
var desiredSize = control.DesiredSize;
Assert.Equal(60, frame.Bottom, 0.5d);
Assert.Equal(60, desiredSize.Height, 0.5d);
});
}

[Fact]
public async Task EditorMeasureUpdatesWhenChangingWidth()
{

await ValidateEditorLayoutChangesForDisabledAutoSize(
null,
(control) => control.WidthRequest = 60,
(control) =>
{
var frame = control.Frame;
var desiredSize = control.DesiredSize;
Assert.Equal(60, frame.Right, 0.5d);
Assert.Equal(60, desiredSize.Width, 0.5d);
});
}

[Fact]
public async Task EditorMeasureUpdatesWhenChangingMargin()
{
await ValidateEditorLayoutChangesForDisabledAutoSize(
null,
(control) => control.Margin = new Thickness(5, 5, 5, 5),
(control) =>
{
var frame = control.Frame;
var desiredSize = control.DesiredSize;
Assert.Equal(55, frame.Right, 0.5d);
Assert.Equal(60, desiredSize.Width, 0.5d);
});
}

[Fact]
public async Task EditorMeasureUpdatesWhenChangingMinHeight()
{
await ValidateEditorLayoutChangesForDisabledAutoSize(
(control) =>
{
control.HeightRequest = Primitives.Dimension.Unset;
},
(control) => control.MinimumHeightRequest = 100,
(control) =>
{
var frame = control.Frame;
var desiredSize = control.DesiredSize;
Assert.Equal(100, frame.Bottom, 0.5d);
Assert.Equal(100, desiredSize.Height, 0.5d);
});
}

[Fact]
public async Task EditorMeasureUpdatesWhenChangingMaxHeight()
{
await ValidateEditorLayoutChangesForDisabledAutoSize(
(control) =>
{
control.HeightRequest = Primitives.Dimension.Unset;
},
(control) => control.MaximumHeightRequest = 10,
(control) =>
{
var frame = control.Frame;
var desiredSize = control.DesiredSize;
Assert.Equal(10, frame.Bottom, 0.5d);
Assert.Equal(10, desiredSize.Height, 0.5d);
});
}

[Fact]
public async Task EditorMeasureUpdatesWhenChangingMinWidth()
{
await ValidateEditorLayoutChangesForDisabledAutoSize(
(control) =>
{
control.WidthRequest = Primitives.Dimension.Unset;
},
(control) => control.MinimumWidthRequest = 100,
(control) =>
{
var frame = control.Frame;
var desiredSize = control.DesiredSize;
Assert.Equal(100, frame.Width, 0.5d);
Assert.Equal(100, desiredSize.Width, 0.5d);
});
}

[Fact]
public async Task EditorMeasureUpdatesWhenChangingMaxWidth()
{
await ValidateEditorLayoutChangesForDisabledAutoSize(
(control) =>
{
control.WidthRequest = Primitives.Dimension.Unset;
control.Text = String.Join(",", Enumerable.Range(0, 100).Select(x => "a").ToArray());
},
(control) =>
{
control.MaximumWidthRequest = 10;
},
(control) =>
{
var frame = control.Frame;
var desiredSize = control.DesiredSize;
Assert.Equal(10, frame.Width, 0.5d);
Assert.Equal(10, desiredSize.Width, 0.5d);
});
}

async Task ValidateEditorLayoutChangesForDisabledAutoSize(
Action<Editor> arrange,
Action<Editor> act,
Action<Editor> assert
)
{
SetupBuilder();
var control = new Editor()
{
AutoSize = EditorAutoSizeOption.Disabled,
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.Start,
};

control.HeightRequest = 50;
control.WidthRequest = 50;
control.MinimumWidthRequest = 0;
control.MaximumWidthRequest = 100;
control.MinimumHeightRequest = 0;
control.MaximumHeightRequest = 100;

IView layout = new VerticalStackLayout()
{
HeightRequest = 100,
WidthRequest = 100,
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.Start,
Children =
{
control
}
};

arrange?.Invoke(control);

await AttachAndRun<LayoutHandler>(layout, async (_) =>
{
await Task.Yield();
var frame = control.Frame;
act.Invoke(control);
await WaitForUIUpdate(frame, control);
assert.Invoke(control);
});
}

static async Task WaitForUIUpdate(Graphics.Rect frame, Editor editor, int timeout = 1000, int interval = 100)
{
// Wait for layout to happen
while (collectionView.Frame == frame && timeout >= 0)
while (editor.Frame == frame && timeout >= 0)
{
await Task.Delay(interval);
timeout -= interval;
Expand Down
47 changes: 47 additions & 0 deletions src/Controls/tests/DeviceTests/Elements/View/ViewTests.cs
Expand Up @@ -20,5 +20,52 @@ namespace Microsoft.Maui.DeviceTests
[Category(TestCategory.View)]
public partial class ViewTests : ControlsHandlerTestBase
{
[Theory]
[ClassData(typeof(TestCases.ControlsViewTypesTestCases))]
public async Task ViewWithMarginSetsFrameAndDesiredSizeCorrectly(Type controlType)
{
EnsureHandlerCreated(TestCases.ControlsViewTypesTestCases.Setup);

var control = Activator.CreateInstance(controlType) as View;

#if MACCATALYST || IOS
if (control is SearchBar sb)
return;
#endif
control.Margin = new Thickness(5, 5, 5, 5);
control.HeightRequest = 50;
control.WidthRequest = 50;
control.MinimumHeightRequest = 0;
control.MinimumWidthRequest = 0;
control.HorizontalOptions = LayoutOptions.Start;
control.VerticalOptions = LayoutOptions.Start;

IView layout = new VerticalStackLayout()
{
HeightRequest = 100,
WidthRequest = 100,
Children =
{
control
}
};

await AttachAndRun<LayoutHandler>(layout, async (_) =>
{
await Task.Yield();
var frame = control.Frame;
var desiredSize = control.DesiredSize;
Assert.Equal(5, frame.X, 0.5d);
Assert.Equal(5, frame.Y, 0.5d);
Assert.Equal(50, frame.Width, 0.5d);
Assert.Equal(50, frame.Height, 0.5d);
Assert.Equal(55, frame.Right, 0.5d);
Assert.Equal(55, frame.Bottom, 0.5d);
Assert.Equal(60, desiredSize.Width, 0.5d);
Assert.Equal(60, desiredSize.Height, 0.5d);
});
}
}
}

0 comments on commit 96288c1

Please sign in to comment.