summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.MacOS/Renderers/CarouselPageRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.MacOS/Renderers/CarouselPageRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.MacOS/Renderers/CarouselPageRenderer.cs229
1 files changed, 229 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.MacOS/Renderers/CarouselPageRenderer.cs b/Xamarin.Forms.Platform.MacOS/Renderers/CarouselPageRenderer.cs
new file mode 100644
index 00000000..014d503b
--- /dev/null
+++ b/Xamarin.Forms.Platform.MacOS/Renderers/CarouselPageRenderer.cs
@@ -0,0 +1,229 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using AppKit;
+using Foundation;
+
+namespace Xamarin.Forms.Platform.MacOS
+{
+ [Register("CarouselPageRenderer")]
+ public class CarouselPageRenderer : NSPageController, IVisualElementRenderer
+ {
+ bool _appeared;
+ bool _disposed;
+ EventTracker _events;
+ VisualElementTracker _tracker;
+
+ public CarouselPageRenderer()
+ {
+ View = new NSView
+ {
+ WantsLayer = true,
+ Layer = { BackgroundColor = NSColor.White.CGColor }
+ };
+ }
+
+ public CarouselPageRenderer(IntPtr handle) : base(handle)
+ {
+ }
+
+ IElementController ElementController => Element;
+
+ IPageController PageController => (IPageController)Element;
+
+ public override nint SelectedIndex
+ {
+ get { return base.SelectedIndex; }
+ set
+ {
+ if (base.SelectedIndex == value)
+ return;
+ base.SelectedIndex = value;
+ if (Carousel != null)
+ Carousel.CurrentPage = (ContentPage)ElementController.LogicalChildren[(int)SelectedIndex];
+ }
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ public NSView NativeView => View;
+
+ public void SetElement(VisualElement element)
+ {
+ VisualElement oldElement = Element;
+ Element = element;
+
+ Init();
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+ }
+
+ public void SetElementSize(Size size)
+ {
+ Element.Layout(new Rectangle(Element.X, Element.Y, size.Width, size.Height));
+ }
+
+ public NSViewController ViewController => 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();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ if (Carousel != null)
+ {
+ Carousel.PropertyChanged -= OnPropertyChanged;
+ Carousel.PagesChanged -= OnPagesChanged;
+ }
+
+ Platform.SetRenderer(Element, null);
+
+ if (_appeared)
+ {
+ _appeared = false;
+ PageController?.SendDisappearing();
+ }
+
+ if (_events != null)
+ {
+ _events.Dispose();
+ _events = null;
+ }
+
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ _tracker = null;
+ }
+
+ Element = null;
+ _disposed = true;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ ElementChanged?.Invoke(this, e);
+ }
+
+ void ConfigureNSPageController()
+ {
+ TransitionStyle = NSPageControllerTransitionStyle.HorizontalStrip;
+ }
+
+ CarouselPage Carousel => Element as CarouselPage;
+
+ void Init()
+ {
+ Delegate = new PageControllerDelegate();
+
+ _tracker = new VisualElementTracker(this);
+ _events = new EventTracker(this);
+ _events.LoadEvents(View);
+
+ ConfigureNSPageController();
+
+ UpdateBackground();
+ UpdateSource();
+
+ Carousel.PropertyChanged += OnPropertyChanged;
+ Carousel.PagesChanged += OnPagesChanged;
+ }
+
+ void UpdateSource()
+ {
+ var pages = new List<NSPageContainer>();
+ for (var i = 0; i < ElementController.LogicalChildren.Count; i++)
+ {
+ Element element = ElementController.LogicalChildren[i];
+ var child = element as ContentPage;
+ if (child != null)
+ pages.Add(new NSPageContainer(child, i));
+ }
+
+ ArrangedObjects = pages.ToArray();
+ UpdateCurrentPage(false);
+ }
+
+ void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ UpdateSource();
+ }
+
+ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(TabbedPage.CurrentPage))
+ UpdateCurrentPage();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackground();
+ else if (e.PropertyName == Page.BackgroundImageProperty.PropertyName)
+ UpdateBackground();
+ }
+
+ void UpdateBackground()
+ {
+ if (View.Layer == null)
+ return;
+
+ 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 UpdateCurrentPage(bool animated = true)
+ {
+ ContentPage current = Carousel.CurrentPage;
+ if (current != null)
+ {
+ int index = Carousel.CurrentPage != null ? CarouselPage.GetIndex(Carousel.CurrentPage) : 0;
+ if (index < 0)
+ index = 0;
+
+ if (SelectedIndex == index)
+ return;
+
+ if (animated)
+ NSAnimationContext.RunAnimation(context => { ((NSPageController)Animator).SelectedIndex = index; },
+ CompleteTransition);
+ else SelectedIndex = index;
+ }
+ }
+ }
+} \ No newline at end of file