summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.iOS/VisualElementPackager.cs')
-rw-r--r--Xamarin.Forms.Platform.iOS/VisualElementPackager.cs179
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