using System; using System.ComponentModel; using AppKit; namespace Xamarin.Forms.Platform.MacOS { public class PageRenderer : NSViewController, IVisualElementRenderer, IEffectControlProvider { bool _init; bool _appeared; bool _disposed; EventTracker _events; VisualElementPackager _packager; VisualElementTracker _tracker; IPageController PageController => Element as IPageController; public PageRenderer() { View = new NSView { WantsLayer = true }; } void IEffectControlProvider.RegisterEffect(Effect effect) { var platformEffect = effect as PlatformEffect; if (platformEffect != null) platformEffect.Container = View; } public VisualElement Element { get; private set; } public event EventHandler ElementChanged; public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) { return NativeView.GetSizeRequest(widthConstraint, heightConstraint); } public NSView NativeView => _disposed ? null : View; public void SetElement(VisualElement element) { VisualElement oldElement = Element; Element = element; UpdateTitle(); OnElementChanged(new VisualElementChangedEventArgs(oldElement, element)); if (Element != null && !string.IsNullOrEmpty(Element.AutomationId)) SetAutomationId(Element.AutomationId); EffectUtilities.RegisterEffectControlProvider(this, oldElement, element); } public void SetElementSize(Size size) { Element.Layout(new Rectangle(Element.X, Element.Y, size.Width, size.Height)); } public NSViewController ViewController => _disposed ? null : this; public override void ViewDidAppear() { base.ViewDidAppear(); if (_appeared || _disposed) return; _appeared = true; PageController.SendAppearing(); } public override void ViewDidDisappear() { base.ViewDidDisappear(); if (!_appeared || _disposed) return; _appeared = false; PageController.SendDisappearing(); } public override void ViewWillAppear() { Init(); base.ViewWillAppear(); } protected override void Dispose(bool disposing) { if (disposing && !_disposed) { Element.PropertyChanged -= OnHandlePropertyChanged; Platform.SetRenderer(Element, null); if (_appeared) PageController.SendDisappearing(); _appeared = false; if (_events != null) { _events.Dispose(); _events = null; } if (_packager != null) { _packager.Dispose(); _packager = null; } if (_tracker != null) { _tracker.Dispose(); _tracker = null; } Element = null; _disposed = true; } base.Dispose(disposing); } void OnElementChanged(VisualElementChangedEventArgs e) { ElementChanged?.Invoke(this, e); } void SetAutomationId(string id) { if (NativeView != null) NativeView.AccessibilityIdentifier = id; } void Init() { if (_init) return; UpdateBackground(); _packager = new VisualElementPackager(this); _packager.Load(); Element.PropertyChanged += OnHandlePropertyChanged; _tracker = new VisualElementTracker(this); _events = new EventTracker(this); _events.LoadEvents(View); _init = true; } void OnHandlePropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName) UpdateBackground(); else if (e.PropertyName == Page.BackgroundImageProperty.PropertyName) UpdateBackground(); else if (e.PropertyName == Page.TitleProperty.PropertyName) UpdateTitle(); } void UpdateBackground() { string bgImage = ((Page)Element).BackgroundImage; if (!string.IsNullOrEmpty(bgImage)) { View.Layer.BackgroundColor = NSColor.FromPatternImage(NSImage.ImageNamed(bgImage)).CGColor; return; } Color bgColor = Element.BackgroundColor; View.Layer.BackgroundColor = bgColor.IsDefault ? NSColor.White.CGColor : bgColor.ToCGColor(); } void UpdateTitle() { if (!string.IsNullOrWhiteSpace(((Page)Element).Title)) Title = ((Page)Element).Title; } } }