Skip to content

Commit

Permalink
IContainer proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
hartez committed Jul 16, 2021
1 parent fba6a03 commit dda7324
Show file tree
Hide file tree
Showing 13 changed files with 169 additions and 80 deletions.
76 changes: 76 additions & 0 deletions src/Controls/src/Core/HandlerImpl/Layout.Impl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.Maui.Controls
{
public abstract partial class Layout<T>
{
int ICollection<IView>.Count => _children.Count;
bool ICollection<IView>.IsReadOnly => ((ICollection<IView>) _children).IsReadOnly;
public IView this[int index] { get => _children[index]; set => _children[index] = (T)value; }

public void Add(IView child)
{
if (child is T view)
{
_children.Add(view);
}
}

public bool Remove(IView child)
{
if (child is T view)
{
_children.Remove(view);
return true;
}

return false;
}

int IList<IView>.IndexOf(IView child)
{
return _children.IndexOf(child);
}

void IList<IView>.Insert(int index, IView child)
{
if (child is T view)
{
_children.Insert(index, view);
}
}

void IList<IView>.RemoveAt(int index)
{
_children.RemoveAt(index);
}

void ICollection<IView>.Clear()
{
_children.Clear();
}

bool ICollection<IView>.Contains(IView child)
{
return _children.Contains(child);
}

void ICollection<IView>.CopyTo(IView[] array, int arrayIndex)
{
_children.CopyTo(array, arrayIndex);
}

IEnumerator<IView> IEnumerable<IView>.GetEnumerator()
{
return _children.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return _children.GetEnumerator();
}
}
}
26 changes: 3 additions & 23 deletions src/Controls/src/Core/Layout.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
Expand All @@ -10,11 +11,8 @@
namespace Microsoft.Maui.Controls
{
[ContentProperty(nameof(Children))]
public abstract class Layout<T> : Layout, Microsoft.Maui.ILayout, IViewContainer<T> where T : View
public abstract partial class Layout<T> : Layout, Microsoft.Maui.ILayout, IViewContainer<T> where T : View
{
// TODO ezhart We should look for a way to optimize this a bit
IReadOnlyList<Microsoft.Maui.IView> Microsoft.Maui.IContainer.Children => Children.ToList();

readonly ElementCollection<T> _children;

protected Layout() => _children = new ElementCollection<T>(InternalChildren);
Expand Down Expand Up @@ -46,28 +44,10 @@ protected virtual void OnAdded(T view)
protected virtual void OnRemoved(T view)
{
}

public void Add(IView child)
{
if (child is T view)
{
Children.Add(view);
}
}

public void Remove(IView child)
{
if (child is T view)
{
Children.Remove(view);
}
}
}

public abstract class Layout : View, ILayout, ILayoutController, IPaddingElement, IFrameworkElement, Microsoft.Maui.IContainer
public abstract class Layout : View, ILayout, ILayoutController, IPaddingElement, IFrameworkElement//, Microsoft.Maui.IContainer
{
IReadOnlyList<Microsoft.Maui.IView> Microsoft.Maui.IContainer.Children => InternalChildren.OfType<IView>().ToList();

public static readonly BindableProperty IsClippedToBoundsProperty =
BindableProperty.Create(nameof(IsClippedToBounds), typeof(bool), typeof(Layout), false);

Expand Down
4 changes: 2 additions & 2 deletions src/Controls/src/Core/Layout/GridLayout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,10 @@ public override void Add(IView child)
}
}

public override void Remove(IView child)
public override bool Remove(IView child)
{
_viewInfo.Remove(child);
base.Remove(child);
return base.Remove(child);
}

protected override ILayoutManager CreateLayoutManager() => new GridLayoutManager(this);
Expand Down
91 changes: 70 additions & 21 deletions src/Controls/src/Core/Layout/Layout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,78 +8,106 @@
namespace Microsoft.Maui.Controls.Layout2
{
[ContentProperty(nameof(Children))]
public abstract class Layout : View, Microsoft.Maui.ILayout, IEnumerable<IView>
public abstract class Layout : View, Maui.ILayout, IList<IView>
{
ILayoutManager _layoutManager;
ILayoutManager LayoutManager => _layoutManager ??= CreateLayoutManager();

readonly List<IView> _children = new List<IView>();
// The actual backing store for the IViews in the ILayout
readonly List<IView> _children = new();

public IReadOnlyList<IView> Children { get => _children.AsReadOnly(); }
// This provides a Children property for XAML
public IList<IView> Children => this;

public ILayoutHandler LayoutHandler => Handler as ILayoutHandler;

public int Count => _children.Count;

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

public IView this[int index] { get => _children[index]; set => _children[index] = value; }

protected abstract ILayoutManager CreateLayoutManager();

public IEnumerator<IView> GetEnumerator() => _children.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => _children.GetEnumerator();

#pragma warning disable CS0672 // Member overrides obsolete member
public override SizeRequest GetSizeRequest(double widthConstraint, double heightConstraint)
#pragma warning restore CS0672 // Member overrides obsolete member
{
var size = (this as IFrameworkElement).Measure(widthConstraint, heightConstraint);
return new SizeRequest(size);
}

protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
{
var margin = (this as IView)?.Margin ?? Thickness.Zero;

// Adjust the constraints to account for the margins
widthConstraint -= margin.HorizontalThickness;
heightConstraint -= margin.VerticalThickness;

var sizeWithoutMargins = LayoutManager.Measure(widthConstraint, heightConstraint);
DesiredSize = new Size(sizeWithoutMargins.Width + Margin.HorizontalThickness,
sizeWithoutMargins.Height + Margin.VerticalThickness);

return DesiredSize;
}

protected override Size ArrangeOverride(Rectangle bounds)
{
base.ArrangeOverride(bounds);

Frame = bounds;

LayoutManager.ArrangeChildren(Frame);

foreach (var child in Children)
{
child.Handler?.NativeArrange(child.Frame);
}

return Frame.Size;
}

protected override void InvalidateMeasureOverride()
{
base.InvalidateMeasureOverride();

foreach (var child in Children)
{
child.InvalidateMeasure();
}
}

public virtual void Add(IView child)
{
if (child == null)
return;

_children.Add(child);
if (child is Element element)
element.Parent = this;
InvalidateMeasure();
LayoutHandler?.Add(child);
}

public void Clear()
{
for (int n = _children.Count - 1; n >= 0; n--)
{
Remove(this[n]);
}
}

public bool Contains(IView item)
{
return _children.Contains(item);
}

public void CopyTo(IView[] array, int arrayIndex)
{
_children.CopyTo(array, arrayIndex);
}

public int IndexOf(IView item)
{
return _children.IndexOf(item);
}

public void Insert(int index, IView child)
{
if (child == null)
return;

_children.Insert(index, child);

if (child is Element element)
element.Parent = this;
Expand All @@ -89,12 +117,33 @@ public virtual void Add(IView child)
LayoutHandler?.Add(child);
}

public virtual void Remove(IView child)
public virtual bool Remove(IView child)
{
if (child == null)
return false;

var result = _children.Remove(child);

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

InvalidateMeasure();

LayoutHandler?.Remove(child);

return result;
}

public void RemoveAt(int index)
{
if (index >= Count)
{
return;
}

var child = _children[index];

_children.Remove(child);
_children.RemoveAt(index);

if (child is Element element)
element.Parent = null;
Expand All @@ -104,4 +153,4 @@ public virtual void Remove(IView child)
LayoutHandler?.Remove(child);
}
}
}
}
7 changes: 2 additions & 5 deletions src/Core/src/Core/IContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ namespace Microsoft.Maui
/// <summary>
/// Provides functionality to act as containers for views.
/// </summary>
public interface IContainer
public interface IContainer : IList<IView>
{
/// <summary>
/// Gets the collection of children that the Container contains.
/// </summary>
IReadOnlyList<IView> Children { get; }

}
}
13 changes: 0 additions & 13 deletions src/Core/src/Core/ILayout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,9 @@ namespace Microsoft.Maui
/// </summary>
public interface ILayout : IView, IContainer
{

/// <summary>
/// Gets the Layout Handler.
/// </summary>
ILayoutHandler LayoutHandler { get; }

/// <summary>
/// Add a child View to the Layout.
/// </summary>
/// <param name="child">The child View to add to the Layout.</param>
void Add(IView child);

/// <summary>
/// Remove a child View from the Layout.
/// </summary>
/// <param name="child">The child View to remove from the Layout.</param>
void Remove(IView child);
}
}
2 changes: 1 addition & 1 deletion src/Core/src/Handlers/Layout/LayoutHandler.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public override void SetVirtualView(IView view)
NativeView.CrossPlatformArrange = VirtualView.Arrange;

NativeView.RemoveAllViews();
foreach (var child in VirtualView.Children)
foreach (var child in VirtualView)
{
NativeView.AddView(child.ToNative(MauiContext));
}
Expand Down
2 changes: 1 addition & 1 deletion src/Core/src/Handlers/Layout/LayoutHandler.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public override void SetVirtualView(IView view)
var oldChildren = NativeView.Subviews.ToList();
oldChildren.ForEach(x => x.RemoveFromSuperview());

foreach (var child in VirtualView.Children)
foreach (var child in VirtualView)
{
NativeView.AddSubview(child.ToNative(MauiContext));
}
Expand Down
2 changes: 1 addition & 1 deletion src/Core/src/HotReload/HotReloadExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static void CheckHandlers(this IView view)

if (view is IContainer layout)
{
foreach (var v in layout.Children)
foreach (var v in layout)
CheckHandlers(v);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Core/src/Layouts/FlexLayoutManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void ArrangeChildren(Rectangle childBounds)
{
FlexLayout.Layout(childBounds.Width, childBounds.Height);

foreach (var child in FlexLayout.Children)
foreach (var child in FlexLayout)
{
var frame = FlexLayout.GetFlexFrame(child);
if (double.IsNaN(frame.X)
Expand Down
Loading

0 comments on commit dda7324

Please sign in to comment.