summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android/RendererPool.cs
blob: 447de3fdf8e58fe9873218598107045b800e8ad7 (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
using System;
using System.Collections.Generic;

namespace Xamarin.Forms.Platform.Android
{
	public sealed class RendererPool
	{
		readonly Dictionary<Type, Stack<IVisualElementRenderer>> _freeRenderers = new Dictionary<Type, Stack<IVisualElementRenderer>>();

		readonly VisualElement _oldElement;

		readonly IVisualElementRenderer _parent;

		public RendererPool(IVisualElementRenderer renderer, VisualElement oldElement)
		{
			if (renderer == null)
				throw new ArgumentNullException("renderer");

			if (oldElement == null)
				throw new ArgumentNullException("oldElement");

			_oldElement = oldElement;
			_parent = renderer;
		}

		public void ClearChildrenRenderers()
		{
			if (((IElementController)_parent.Element).LogicalChildren.Count == 0)
				return;
			ClearChildrenRenderers(_oldElement);
		}

		public IVisualElementRenderer GetFreeRenderer(VisualElement view)
		{
			if (view == null)
				throw new ArgumentNullException("view");

			Type rendererType = Registrar.Registered.GetHandlerType(view.GetType()) ?? typeof(ViewRenderer);

			Stack<IVisualElementRenderer> renderers;
			if (!_freeRenderers.TryGetValue(rendererType, out renderers) || renderers.Count == 0)
				return null;

			IVisualElementRenderer renderer = renderers.Pop();
			renderer.SetElement(view);
			return renderer;
		}

		void ClearChildrenRenderers(VisualElement view)
		{
			if (view == null)
				return;

			foreach (Element logicalChild in ((IElementController)view).LogicalChildren)
			{
				var child = logicalChild as VisualElement;
				if (child != null)
				{
					IVisualElementRenderer renderer = Platform.GetRenderer(child);
					if (renderer == null)
						continue;

					if (renderer.ViewGroup.Parent != _parent.ViewGroup)
						continue;

					renderer.ViewGroup.RemoveFromParent();

					Platform.SetRenderer(child, null);
					PushRenderer(renderer);
				}
			}

			if (_parent.ViewGroup.ChildCount != 0)
				_parent.ViewGroup.RemoveAllViews();
		}

		void PushRenderer(IVisualElementRenderer renderer)
		{
			Type rendererType = renderer.GetType();

			Stack<IVisualElementRenderer> renderers;
			if (!_freeRenderers.TryGetValue(rendererType, out renderers))
				_freeRenderers[rendererType] = renderers = new Stack<IVisualElementRenderer>();

			renderers.Push(renderer);
		}
	}
}