diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 13:02:25 -0700 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 16:13:41 -0700 |
commit | 17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch) | |
tree | b5e5073a2a7b15cdbe826faa5c763e270a505729 /Xamarin.Forms.Platform.iOS/VisualElementPackager.cs | |
download | xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.gz xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.bz2 xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.zip |
Initial import
Diffstat (limited to 'Xamarin.Forms.Platform.iOS/VisualElementPackager.cs')
-rw-r--r-- | Xamarin.Forms.Platform.iOS/VisualElementPackager.cs | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs b/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs new file mode 100644 index 00000000..7f511d9d --- /dev/null +++ b/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs @@ -0,0 +1,179 @@ +using System; +#if __UNIFIED__ +using UIKit; + +#else +using MonoTouch.UIKit; +#endif + +namespace Xamarin.Forms.Platform.iOS +{ + public class VisualElementPackager : IDisposable + { + VisualElement _element; + + bool _isDisposed; + + public VisualElementPackager(IVisualElementRenderer renderer) + { + if (renderer == null) + throw new ArgumentNullException("renderer"); + + Renderer = renderer; + renderer.ElementChanged += OnRendererElementChanged; + SetElement(null, renderer.Element); + } + + protected IVisualElementRenderer Renderer { get; set; } + + public void Dispose() + { + Dispose(true); + } + + public void Load() + { + for (var i = 0; i < Renderer.Element.LogicalChildren.Count; i++) + { + var child = Renderer.Element.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; + + var viewRenderer = Platform.CreateRenderer(view); + Platform.SetRenderer(view, viewRenderer); + + var uiview = Renderer.NativeView; + uiview.AddSubview(viewRenderer.NativeView); + + if (Renderer.ViewController != null && viewRenderer.ViewController != null) + Renderer.ViewController.AddChildViewController(viewRenderer.ViewController); + + EnsureChildrenOrder(); + } + + protected virtual void OnChildRemoved(VisualElement view) + { + var viewRenderer = Platform.GetRenderer(view); + if (viewRenderer == null || viewRenderer.NativeView == null) + return; + + viewRenderer.NativeView.RemoveFromSuperview(); + + if (Renderer.ViewController != null && viewRenderer.ViewController != null) + viewRenderer.ViewController.RemoveFromParentViewController(); + } + + void EnsureChildrenOrder() + { + if (Renderer.Element.LogicalChildren.Count == 0) + return; + + for (var z = 0; z < Renderer.Element.LogicalChildren.Count; z++) + { + var child = Renderer.Element.LogicalChildren[z] as VisualElement; + if (child == null) + continue; + var childRenderer = Platform.GetRenderer(child); + + if (childRenderer == null) + continue; + + var nativeControl = childRenderer.NativeView; + + Renderer.NativeView.BringSubviewToFront(nativeControl); + nativeControl.Layer.ZPosition = 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 + { + for (var i = 0; i < oldElement.LogicalChildren.Count; i++) + { + var child = oldElement.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(); + } + } +}
\ No newline at end of file |