Ooui-tws-port/Ooui.Forms/VisualElementPackager.cs

183 lines
5.5 KiB
C#

using System;
using Xamarin.Forms;
namespace Ooui.Forms
{
public class VisualElementPackager : IDisposable
{
VisualElement _element;
bool _isDisposed;
IElementController ElementController => _element;
public VisualElementPackager (IVisualElementRenderer renderer) : this (renderer, null)
{
}
VisualElementPackager (IVisualElementRenderer renderer, VisualElement element)
{
if (renderer == null)
throw new ArgumentNullException (nameof (renderer));
Renderer = renderer;
renderer.ElementChanged += OnRendererElementChanged;
SetElement (null, element ?? renderer.Element);
}
protected IVisualElementRenderer Renderer { get; set; }
public void Dispose ()
{
Dispose (true);
}
public void Load ()
{
for (var i = 0; i < ElementController.LogicalChildren.Count; i++) {
var child = ElementController.LogicalChildren[i] as VisualElement;
if (child != null)
OnChildAdded (child);
}
}
protected virtual void Dispose (bool disposing)
{
if (_isDisposed)
return;
if (disposing) {
SetElement (_element, null);
if (Renderer != null) {
Renderer.ElementChanged -= OnRendererElementChanged;
Renderer = null;
}
}
_isDisposed = true;
}
protected virtual void OnChildAdded (VisualElement view)
{
if (_isDisposed)
return;
//if (CompressedLayout.GetIsHeadless (view)) {
// var packager = new VisualElementPackager (Renderer, view);
// view.IsPlatformEnabled = true;
// packager.Load ();
//}
//else {
var viewRenderer = Platform.CreateRenderer (view);
Platform.SetRenderer (view, viewRenderer);
var uiview = Renderer.NativeView;
uiview.AppendChild (viewRenderer.NativeView);
EnsureChildrenOrder ();
//}
}
protected virtual void OnChildRemoved (VisualElement view)
{
if (_element == null)
return;
var viewRenderer = Platform.GetRenderer (view);
if (viewRenderer == null || viewRenderer.NativeView == null)
return;
var parentRenderer = Platform.GetRenderer (_element);
if (parentRenderer == null || parentRenderer.NativeView == null)
return;
parentRenderer.NativeView.RemoveChild (viewRenderer.NativeView);
}
void EnsureChildrenOrder ()
{
if (ElementController.LogicalChildren.Count == 0)
return;
for (var z = 0; z < ElementController.LogicalChildren.Count; z++) {
var child = ElementController.LogicalChildren[z] as VisualElement;
if (child == null)
continue;
var childRenderer = Platform.GetRenderer (child);
if (childRenderer == null)
continue;
var nativeControl = childRenderer.NativeView;
#if __MOBILE__
Renderer.NativeView.BringSubviewToFront(nativeControl);
#endif
nativeControl.Style.ZIndex = z * 1000;
}
}
void OnChildAdded (object sender, ElementEventArgs e)
{
var view = e.Element as VisualElement;
if (view != null)
OnChildAdded (view);
}
void OnChildRemoved (object sender, ElementEventArgs e)
{
var view = e.Element as VisualElement;
if (view != null)
OnChildRemoved (view);
}
void OnRendererElementChanged (object sender, VisualElementChangedEventArgs args)
{
if (args.NewElement == _element)
return;
SetElement (_element, args.NewElement);
}
void SetElement (VisualElement oldElement, VisualElement newElement)
{
if (oldElement == newElement)
return;
if (oldElement != null) {
oldElement.ChildAdded -= OnChildAdded;
oldElement.ChildRemoved -= OnChildRemoved;
oldElement.ChildrenReordered -= UpdateChildrenOrder;
if (newElement != null) {
var pool = new RendererPool (Renderer, oldElement);
pool.UpdateNewElement (newElement);
EnsureChildrenOrder ();
}
else {
var elementController = ((IElementController)oldElement);
for (var i = 0; i < elementController.LogicalChildren.Count; i++) {
var child = elementController.LogicalChildren[i] as VisualElement;
if (child != null)
OnChildRemoved (child);
}
}
}
_element = newElement;
if (newElement != null) {
newElement.ChildAdded += OnChildAdded;
newElement.ChildRemoved += OnChildRemoved;
newElement.ChildrenReordered += UpdateChildrenOrder;
}
}
void UpdateChildrenOrder (object sender, EventArgs e)
{
EnsureChildrenOrder ();
}
}
}