Skip to content

Commit f0e8ea7

Browse files
authored
IContainer as IList<IView> (#1724)
* IContainer proposal * Update the test classes to match the updated interfaces * Make substitution work for new layout interface * Fix Windows * Implement methods on stub I missed * And another thing I forgot to implement * Remove commented code * Make IContainer implementation explicit * Fix child collection access in test
1 parent 870d784 commit f0e8ea7

23 files changed

+254
-207
lines changed

src/Compatibility/Core/src/iOS/Resources/StringResources.Designer.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
6+
namespace Microsoft.Maui.Controls
7+
{
8+
public abstract partial class Layout<T>
9+
{
10+
int ICollection<IView>.Count => _children.Count;
11+
bool ICollection<IView>.IsReadOnly => ((ICollection<IView>) _children).IsReadOnly;
12+
public IView this[int index] { get => _children[index]; set => _children[index] = (T)value; }
13+
14+
void ICollection<IView>.Add(IView child)
15+
{
16+
if (child is T view)
17+
{
18+
_children.Add(view);
19+
}
20+
}
21+
22+
bool ICollection<IView>.Remove(IView child)
23+
{
24+
if (child is T view)
25+
{
26+
_children.Remove(view);
27+
return true;
28+
}
29+
30+
return false;
31+
}
32+
33+
int IList<IView>.IndexOf(IView child)
34+
{
35+
return _children.IndexOf(child);
36+
}
37+
38+
void IList<IView>.Insert(int index, IView child)
39+
{
40+
if (child is T view)
41+
{
42+
_children.Insert(index, view);
43+
}
44+
}
45+
46+
void IList<IView>.RemoveAt(int index)
47+
{
48+
_children.RemoveAt(index);
49+
}
50+
51+
void ICollection<IView>.Clear()
52+
{
53+
_children.Clear();
54+
}
55+
56+
bool ICollection<IView>.Contains(IView child)
57+
{
58+
return _children.Contains(child);
59+
}
60+
61+
void ICollection<IView>.CopyTo(IView[] array, int arrayIndex)
62+
{
63+
_children.CopyTo(array, arrayIndex);
64+
}
65+
66+
IEnumerator<IView> IEnumerable<IView>.GetEnumerator()
67+
{
68+
return _children.GetEnumerator();
69+
}
70+
71+
IEnumerator IEnumerable.GetEnumerator()
72+
{
73+
return _children.GetEnumerator();
74+
}
75+
}
76+
}

src/Controls/src/Core/Layout.cs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections;
23
using System.Collections.Generic;
34
using System.Collections.ObjectModel;
45
using System.Collections.Specialized;
@@ -10,11 +11,8 @@
1011
namespace Microsoft.Maui.Controls
1112
{
1213
[ContentProperty(nameof(Children))]
13-
public abstract class Layout<T> : Layout, Microsoft.Maui.ILayout, IViewContainer<T> where T : View
14+
public abstract partial class Layout<T> : Layout, Microsoft.Maui.ILayout, IViewContainer<T> where T : View
1415
{
15-
// TODO ezhart We should look for a way to optimize this a bit
16-
IReadOnlyList<Microsoft.Maui.IView> Microsoft.Maui.IContainer.Children => Children.ToList();
17-
1816
readonly ElementCollection<T> _children;
1917

2018
protected Layout() => _children = new ElementCollection<T>(InternalChildren);
@@ -46,28 +44,10 @@ protected virtual void OnAdded(T view)
4644
protected virtual void OnRemoved(T view)
4745
{
4846
}
49-
50-
public void Add(IView child)
51-
{
52-
if (child is T view)
53-
{
54-
Children.Add(view);
55-
}
56-
}
57-
58-
public void Remove(IView child)
59-
{
60-
if (child is T view)
61-
{
62-
Children.Remove(view);
63-
}
64-
}
6547
}
6648

67-
public abstract class Layout : View, ILayout, ILayoutController, IPaddingElement, IFrameworkElement, Microsoft.Maui.IContainer
49+
public abstract class Layout : View, ILayout, ILayoutController, IPaddingElement, IFrameworkElement
6850
{
69-
IReadOnlyList<Microsoft.Maui.IView> Microsoft.Maui.IContainer.Children => InternalChildren.OfType<IView>().ToList();
70-
7151
public static readonly BindableProperty IsClippedToBoundsProperty =
7252
BindableProperty.Create(nameof(IsClippedToBounds), typeof(bool), typeof(Layout), false);
7353

src/Controls/src/Core/Layout/GridLayout.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,10 @@ public override void Add(IView child)
231231
}
232232
}
233233

234-
public override void Remove(IView child)
234+
public override bool Remove(IView child)
235235
{
236236
_viewInfo.Remove(child);
237-
base.Remove(child);
237+
return base.Remove(child);
238238
}
239239

240240
protected override ILayoutManager CreateLayoutManager() => new GridLayoutManager(this);

src/Controls/src/Core/Layout/Layout.cs

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,8 @@ public abstract class Layout : View, Microsoft.Maui.ILayout, IList<IView>, IPadd
2525

2626
public bool IsReadOnly => ((ICollection<IView>)_children).IsReadOnly;
2727

28-
IReadOnlyList<IView> IContainer.Children => _children.AsReadOnly();
29-
3028
public IView this[int index] { get => _children[index]; set => _children[index] = value; }
3129

32-
3330
public Thickness Padding
3431
{
3532
get => (Thickness)GetValue(PaddingElement.PaddingProperty);
@@ -53,56 +50,44 @@ public override SizeRequest GetSizeRequest(double widthConstraint, double height
5350
protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
5451
{
5552
var margin = (this as IView)?.Margin ?? Thickness.Zero;
56-
5753
// Adjust the constraints to account for the margins
5854
widthConstraint -= margin.HorizontalThickness;
5955
heightConstraint -= margin.VerticalThickness;
60-
6156
var sizeWithoutMargins = LayoutManager.Measure(widthConstraint, heightConstraint);
6257
DesiredSize = new Size(sizeWithoutMargins.Width + Margin.HorizontalThickness,
6358
sizeWithoutMargins.Height + Margin.VerticalThickness);
64-
6559
return DesiredSize;
6660
}
67-
61+
6862
protected override Size ArrangeOverride(Rectangle bounds)
6963
{
7064
base.ArrangeOverride(bounds);
71-
7265
Frame = bounds;
73-
7466
LayoutManager.ArrangeChildren(Frame);
75-
7667
foreach (var child in Children)
7768
{
7869
child.Handler?.NativeArrange(child.Frame);
7970
}
80-
8171
return Frame.Size;
8272
}
8373

8474
protected override void InvalidateMeasureOverride()
8575
{
8676
base.InvalidateMeasureOverride();
87-
8877
foreach (var child in Children)
8978
{
9079
child.InvalidateMeasure();
9180
}
9281
}
93-
82+
9483
public virtual void Add(IView child)
9584
{
9685
if (child == null)
9786
return;
98-
9987
_children.Add(child);
100-
10188
if (child is Element element)
10289
element.Parent = this;
103-
10490
InvalidateMeasure();
105-
10691
LayoutHandler?.Add(child);
10792
}
10893

@@ -144,19 +129,21 @@ public void Insert(int index, IView child)
144129
LayoutHandler?.Add(child);
145130
}
146131

147-
public virtual void Remove(IView child)
132+
public virtual bool Remove(IView child)
148133
{
149134
if (child == null)
150-
return;
135+
return false;
151136

152-
_children.Remove(child);
137+
var result = _children.Remove(child);
153138

154139
if (child is Element element)
155140
element.Parent = null;
156141

157142
InvalidateMeasure();
158143

159144
LayoutHandler?.Remove(child);
145+
146+
return result;
160147
}
161148

162149
public void RemoveAt(int index)
@@ -178,23 +165,6 @@ public void RemoveAt(int index)
178165
LayoutHandler?.Remove(child);
179166
}
180167

181-
bool ICollection<IView>.Remove(IView child)
182-
{
183-
if (child == null)
184-
return false;
185-
186-
var result = _children.Remove(child);
187-
188-
if (child is Element element)
189-
element.Parent = null;
190-
191-
InvalidateMeasure();
192-
193-
LayoutHandler?.Remove(child);
194-
195-
return result;
196-
}
197-
198168
void IPaddingElement.OnPaddingPropertyChanged(Thickness oldValue, Thickness newValue)
199169
{
200170
InvalidateMeasure();

src/Controls/tests/Core.UnitTests/Layouts/LayoutCompatTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public void GridInsideStackLayout()
9797
view.GetDesiredSize(default, default).ReturnsForAnyArgs(expectedSize);
9898
label.Handler = view;
9999

100-
stackLayout.Add(grid);
100+
stackLayout.Children.Add(grid);
101101
grid.Children.Add(label);
102102
contentPage.Content = stackLayout;
103103

src/Core/src/Core/IContainer.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@ namespace Microsoft.Maui
55
/// <summary>
66
/// Provides functionality to act as containers for views.
77
/// </summary>
8-
public interface IContainer
8+
public interface IContainer : IList<IView>
99
{
10-
/// <summary>
11-
/// Gets the collection of children that the Container contains.
12-
/// </summary>
13-
IReadOnlyList<IView> Children { get; }
10+
1411
}
1512
}

src/Core/src/Core/ILayout.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,6 @@ public interface ILayout : IView, IContainer
1313
/// </summary>
1414
ILayoutHandler LayoutHandler { get; }
1515

16-
/// <summary>
17-
/// Add a child View to the Layout.
18-
/// </summary>
19-
/// <param name="child">The child View to add to the Layout.</param>
20-
void Add(IView child);
21-
22-
/// <summary>
23-
/// Remove a child View from the Layout.
24-
/// </summary>
25-
/// <param name="child">The child View to remove from the Layout.</param>
26-
void Remove(IView child);
27-
2816
/// <summary>
2917
/// The space between the outer edge of the ILayout's content area and its children.
3018
/// </summary>

src/Core/src/Handlers/Layout/LayoutHandler.Android.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public override void SetVirtualView(IView view)
3333
NativeView.CrossPlatformArrange = VirtualView.Arrange;
3434

3535
NativeView.RemoveAllViews();
36-
foreach (var child in VirtualView.Children)
36+
foreach (var child in VirtualView)
3737
{
3838
NativeView.AddView(child.ToNative(MauiContext));
3939
}

src/Core/src/Handlers/Layout/LayoutHandler.Windows.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public override void SetVirtualView(IView view)
2626
NativeView.CrossPlatformArrange = VirtualView.Arrange;
2727

2828
NativeView.Children.Clear();
29-
foreach (var child in VirtualView.Children)
29+
foreach (var child in VirtualView)
3030
{
3131
Add(child);
3232
}

0 commit comments

Comments
 (0)