summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.MacOS/Cells/ViewCellNSView.cs
blob: 6b342c229bcbdc4a7b4cb39c3aef6d79c77ddabe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using AppKit;
using RectangleF = CoreGraphics.CGRect;

namespace Xamarin.Forms.Platform.MacOS
{
	internal class ViewCellNSView : CellNSView
	{
		public ViewCellNSView() : base(NSTableViewCellStyle.Empty)
		{

		}

		WeakReference<IVisualElementRenderer> _rendererRef;

		ViewCell _viewCell;

		public override Element Element => ViewCell;

		public ViewCell ViewCell
		{
			get { return _viewCell; }
			set
			{
				if (_viewCell == value)
					return;
				UpdateCell(value);
			}
		}

		public override void Layout()
		{
			LayoutSubviews();
			base.Layout();
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				IVisualElementRenderer renderer;
				if (_rendererRef != null && _rendererRef.TryGetTarget(out renderer) && renderer.Element != null)
				{
					Platform.DisposeModelAndChildrenRenderers(renderer.Element);

					_rendererRef = null;
				}
			}

			base.Dispose(disposing);
		}

		void LayoutSubviews()
		{
			var contentFrame = Frame;
			var view = ViewCell.View;

			Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion(view, contentFrame.ToRectangle());

			if (_rendererRef == null)
				return;

			IVisualElementRenderer renderer;
			if (_rendererRef.TryGetTarget(out renderer))
				renderer.NativeView.Frame = view.Bounds.ToRectangleF();
		}

		IVisualElementRenderer GetNewRenderer()
		{
			var newRenderer = Platform.CreateRenderer(_viewCell.View);
			_rendererRef = new WeakReference<IVisualElementRenderer>(newRenderer);
			AddSubview(newRenderer.NativeView);
			return newRenderer;
		}

		void UpdateCell(ViewCell cell)
		{
			ICellController cellController = _viewCell;
			if (cellController != null)
				Device.BeginInvokeOnMainThread(cellController.SendDisappearing);

			_viewCell = cell;
			cellController = cell;

			Device.BeginInvokeOnMainThread(cellController.SendAppearing);

			IVisualElementRenderer renderer;
			if (_rendererRef == null || !_rendererRef.TryGetTarget(out renderer))
				renderer = GetNewRenderer();
			else
			{
				if (renderer.Element != null && renderer == Platform.GetRenderer(renderer.Element))
					renderer.Element.ClearValue(Platform.RendererProperty);

				var type = Registrar.Registered.GetHandlerType(_viewCell.View.GetType());
				if (renderer.GetType() == type || (renderer is DefaultRenderer && type == null))
					renderer.SetElement(_viewCell.View);
				else
				{
					//when cells are getting reused the element could be already set to another cell
					//so we should dispose based on the renderer and not the renderer.Element
					Platform.DisposeRendererAndChildren(renderer);
					renderer = GetNewRenderer();
				}
			}

			Platform.SetRenderer(_viewCell.View, renderer);
		}
	}
}