diff options
author | Rui Marinho <me@ruimarinho.net> | 2017-01-26 15:33:15 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-26 15:33:15 +0000 |
commit | 52fc04724fc163c68c54cf33a5931871f8c1ee8e (patch) | |
tree | 28a56527e0886e616735d5334f7b10688c255074 /Xamarin.Forms.Platform.iOS | |
parent | 6b2a69d930d42657aff2b9ad769503b4939568ab (diff) | |
download | xamarin-forms-52fc04724fc163c68c54cf33a5931871f8c1ee8e.tar.gz xamarin-forms-52fc04724fc163c68c54cf33a5931871f8c1ee8e.tar.bz2 xamarin-forms-52fc04724fc163c68c54cf33a5931871f8c1ee8e.zip |
MacOS (#650)
* [MacOS] Add SwitchRenderer
* [MacOS] Add TimePickerRenderer
* [MacOS] Cleanup TimePcikerRender
* [MacOS] Add WebViewRenderer
* [MacOS] Add Javascript evaluate to webview
* [MacOS] Fix build error on WebViewRenderer
* [MacOS] Add Base and TextCell renderers
* [MacOS] Start on ListViewRenderer
* [MacOS] Cleanup
* [MacOS] Vertical center text on default NSTextField
* [MacOS] Center NSTextField vertically
* [MacOS] Add ImageCellRenderer
* [MacOS] Add SwitchCellRenderer
* [MacOS] Add SwitchCellRenderer
* [iOS] Allow to set background color on other CellRenderers
* [MacOS] Fix selection mode on ListView
* [MacOS] Set background on Entry of entry cell
* [MacOS] Fix casting bug on CellRenderer
* [MacOS] Other fix on CellRenderer background
* [MacOS] Add ViewCellRenderer
* [MacOS] Fixes and cleanup on cells
* [MacOS] Add NSScrollView so NSTableView can scroll
* [MacOS] Add HeaderView to ListView
* [MacOS] Cleanup
* [Controls] Add Header support to ListView
* [MacOS] NSView reuse on NSTableView
* [MacOS] Some fix on layour order
* [MacOS] Add CarouselPageRenderer
* [MacOS] Implement EventTracker on PageRenderer
* [MacOS] Cleanup CarouselPageRenderer
* [MacOS] Add MasterDetailPage renderer
* [MacOS] MDP renderer don't allow drag of splitter
* [MacOS] Add TabbedPage renderer
* [MacOS] Initial sketch of NavigationPageRenderer
* [MacOS] Send disappearing of CurrentPage on Dispose on NavigationPageRenderer
* [MacOS] Add Gallery page for Mac
* [MacOS] Add MacOSExpressionSearch
* [MacOS] Fix ColorExtension
* [MacOS] Fix MDP renderer layout
* [MacOS] Implement native selection on ListViewRenderer
* [MacOS] Deselect a item on NSTableView
* [MacOS] Remove previous SplitViewItems
* [MacOS] Fix navigationpage height
* [MacOS] Add toolbar for NavigationPageRenderer
* [MacOS] Don't remove selection for now (crashing)
* [MacOS] Refactor page and back button title on NavigationPageRenderer
* [MacOS] Fix bug when native navigate back
* [MacOS] Hide layer when transition
* [MacOS] ListviewRenderer fix BbackgroundColor
* [MacOS] Fix background on ScrollViewRenderer
* [MacOS] Fix header measure on ListViewRenderer
* [MacOS] Add Mac twitter demo
* [Controls] Spaces for easy reading
* [MacOS] More xaml cleanup
* [Core] Add Mac as aTargetPlatform
* [MacOS] Add alerts and actionsheets
* [MacOS] Add GestureRecognizers
* [MacOS] Fix Layout issues when adding children, enable transformations
* [MacOS] Fix title on tab item, move to tabbed navigation based on segmented control
* [MacOS] Hide toolbar when not needed, this allows to work with tabbed page, cleanup
* [MacOS] Add NativeBindings and NativeViewWrapper
* [MacOS] Fix AssemblyInfo
* [MacOS] FIX NRE on SetBackgroundColor BoxView
* [MacOS] Fix NavigationPageRenderer
* [MacOS] Fix build
* [MacOS] Also update page when it resizes
* [MacOS] Add LayoutRenderer for handle items position when the bounds change.
* [MacOS] Refactor/Cleanup
* [MacOS] Add toolbar items support to NavigationPage
* [MacOS] Resize images for TabViewITems
* [MacOS] Fix TabbedPage resize issues , allow users to override some features when creating TVI
* [MacOS] Fix hide/show Navigation toolbar
* [MacOS] Redo CarouselPageRenderer with NSPageController
* [MacOS] Add support for Modal pages
* [MacOS] Refactor navigation from platform
* [Nuget] Add nuget for MacOS
* [Nuget]Fix nuspec
* [Nuget] Add variables for CI
* [Controls] Remove MainMenu from MacOS
* [MacOS] Add TableView renderer (no headers yet)
* [MacOS] Refactoring, marking extensions as internal
* [MacOS] Add group headers for TableViewRenderer
* [MacOS] Workaround for updates on listview collection
* [MacOS] Handle updates of rows in the ListViewRenderer properly
* [MacOS] Fix navigation animation
* Fix navigation header issues with modal pages
* [MacOS] Fix MDP issues with resizing
* [MacOS] Fix general dispose
* [MacOS] Add a ViewControllerWrapper for NSSplitView
* [MacOS] MDP renderer fix animation
* [MacOS] Fix ListView selection bug
* [MacOS] Fix rendering MDP Layout inside wrappers
* [MacOS] Re write the MainToolbar handler
* [MacOS] Don't use Sierra new extensions so we can run in stable channel
* [MacOS] Another way to hide the toolbar (smarter i think)
* [MacOS] Fix MDP bug and remove debug color
* [Controls] Add HanselForms sample
* [MacOS] Fix NRE WebviewRenderer
* [MacOS] Fix uneven rows on ListView renderer
* [MacOS] Fix NRE on load (can+t find the reason this happens)
* [MacOS] Fix uneven rows
* [MacOS] Fix header sizing on ListViewRenderer
* [Controls] More stuff on HanselForms
* [MacOS] Remove warning from ListViewRenderer
* [MacOS] Fix PageRenderer bug double init
* [MacOS] Don't calculate height if RowHeight is provided
* [Controls] More Hanselforms stuff
* [MacOS] Once again a new implementation for the NavigationBar, this time using a custom view to support BackgroundColor
* [MacOS] Fix build
* [MacOS] Refactoring AwesomeBar related controls
* Fix build
* [MacOS] NavigationBar update background and t test colors
* [MacOS] Fix when we remove navigation so it works when the NavigationRenderer wasn't removed from the parent controller like in a TabbedPage
* [MacOS] Add support for ListView grouping
* [MacOS] Fix image extension method.
* [MacOS] Add base Maps project
* [MacOS] Export MapRenderer
* [MacOS] Add pin click and geocoderbacked for Maps
* [MacOS] Add extra binding project for API not in stable.
* [MacOS] Add MacOS Maps lib
* [MacOS]Fix build on alpha
* [MacOS] Remove MacOS Maps extra binding
* [UITest] Basic macOS setup
* [UITest] Add MacOSApp wrapper implementation
* [MacOS] Set AutomationID
* [UITests] Add ActionSheetUITests to MacOS UITest
* [MacOS] Fix bug on Picker
* [UITests] Link basic uitest basefixture and related files
* [MacOS] Fix pickers reuse
* [UItests] Fix MacOS app path
* [UITest] Ignore UItest for appearing on macOS for now
* [UITest] Update macOS for 2.0.3
* [UITest] Refactor EnterText MacOS app
* [UITest]Fix ViewQuery on MacOS
* [UITest]Fix IsEnabled UItest on macOS
* [UITest] Implement Enter, mark some tests inconclusive fix others
* [MacOS] Implement Entry Completed event
* [UITests] Fix UITest for IsVisible, ignore ToolbarItem test for now
* [UITests] Fix ISVisible again add extra category
* [Controls] Cleanup macOS gallery
* [MacOS] Fix Assembly info
* [Docs] Fix docs
* Fix build
* [Nuget] Fix nuspec
* [Controls] Link files on MacOS
* [Core] Update Forms stack before firing a event saying page was removed, possible breaking change
* [MacOS] Implement RemovePage on NavigationPAgeRenderer
* [UItest] Ignore some , implement back on MacOS UITest app
* [MacOS] Add default back button name (needs to be translated)
* [MacOS] Fix dispose
* [UITest] Make 29257 work on MacOS
* [MacOS] Rename stuff
* [MacOS] More renaming and cleanup
* [MacOS] Share implementations for iOS
* [MacOS] Reuse more IOS extensions
* [MacOS] Reuse FontExtensions
* [MacOS] Share NativeViewWrapper related stuff
* [MAcOS] Share event args and ExportRenderer
* [MacOS] Share platform effect
* [MacOS] Fix build
* [Docs]Fixing docs
* [MacOS] Fix ViewCell reuse
* [Core] Support ListView CachingStrategy on MacOS
* [MacOS] Fix issues with TextCell and ImageCell (we can’t set null to a NSControl value)
* [MacOS] Fix MDP child sizing bug
[UITest] Query marked by id and text
* [MacOS] Comment test related with context actions
* [MacOS] Implement missing stuff on ticker
* [MacOS] Make sure VisualElemenTracker calls the ticker update
* [UITests]Ignore context actions and not possible to test
* [MacOS] Fix Grouping bug on Listview
* [MacOS] Fix selection on Listview when using grouping
* [MacOS] Update navbar when page is popped
* [MacOS] Cleanup NavigationBar
* [Controls] More info on exceptions
* [MacOS] Fix bug animation pop modal
* [MacOS] Bring back BackgroundColor of NavigationBar
* [MacOS] Fix UITest animation delay
* [MacOS] Treat warnings as errors
* [MacOS] Center title on toolbar
* [Core] Add Platform configuration specific for MacOS
* [MacOS] Implement TabbedPage platform specific to handle TabItems on NavigationPage bar
* [MacOS] Fix warning
* [MacOS] Fix bug on SearchBar color
* [MacOS]Fix build
* [MacOS] remove extra dll from maps
* [Docs] Update docs
* [MacOS]Cleanup and refactoring
* Revert "[MacOS] remove extra dll from maps"
This reverts commit 73b948937001fea3f28449a963d0b94943e07aa0.
* [MacOS] Fix wrong refactoring
* [MacOS] Remove gallery and uitest project
* [MacOS] dix formatting
* [MacOS] Remove extra stuff
* Merge branch 'master' into macOS-gallery
* [MacOS] Fix rebase
* [MacOS] Fix TargetPlatform
* fix docs
* [MacOS] Fix bug on TabbedPageRenderer no title
* [MacOS] Remove FormsNSView
* [MacOS] Cleanup on dispose on MDP renderer
* [MacOS] Update current page when source changes
* [MacOS] More cleanup
* [MacOS] Make sure we show the previous page when popping a Modal
* [MacOS] Fix issue with sizing the Header and visibility, remove for now header renderer reuse
* [MacOS] Clean CustomNSTableView
* [MacOS] Share LabelRenderer with iOS
* [MacOS] Share ResourcesProvider with iOS
* [MAcoS] Share VisualElementPackager with iOS
* [MacOS] Share ViewRenderer with iOS
* [MacOS] Merge with VisualElementTracker from iOS
* [MacOS] Merge with EventTracker from iOS
* [MacOS] Merge with VisualElementRenderer of iOS
* [MacOS] Make sure we always have a layer
* [MacOS] Fix Tracker merge with iOS version
* [MacOS] Fix bug with tabbed page on modal without navigation
* [Core] Rever change on core
* [MacOS] Clear renderers before setting them MDP
* [MacOS] Update tabbedPage ContainerArea
* [MacOS] Fix ListViewRenderer
* [MacOS] Make sure we don’t pass null to TextField string value
* [MacOS] Support for multiple clicks in same selected item on NSTableView
* [MacOS] Support Focus on EntryRenderer
* [MacOS] Fix index bug on TablevIewDataSource
* [MacOS] Fix SelectedItem TableViewDataSource
* [Nuget] Add Mac to Maps nuspec
* [Nuget]Fix path
* [macOS] Fixed Tab NSImage crash in TabbedPageRenderer (#705)
* [macOS] Fixed Tab NSImage crash in TabbedPageRenderer
* Coding Style
* Coding Style
* [MacOS] Fix previous merge with master
* [MacOS] Possible simple fix for click on views overlapping
* [MacOS] Rename to IsOnViewCell
* [MacOS] Cleanup, Address feedback from Samantha’s review
Diffstat (limited to 'Xamarin.Forms.Platform.iOS')
27 files changed, 767 insertions, 134 deletions
diff --git a/Xamarin.Forms.Platform.iOS/Deserializer.cs b/Xamarin.Forms.Platform.iOS/Deserializer.cs index 86657578..dcef049c 100644 --- a/Xamarin.Forms.Platform.iOS/Deserializer.cs +++ b/Xamarin.Forms.Platform.iOS/Deserializer.cs @@ -6,7 +6,12 @@ using System.Runtime.Serialization; using System.Threading.Tasks; using System.Xml; +#if __MOBILE__ namespace Xamarin.Forms.Platform.iOS +#else + +namespace Xamarin.Forms.Platform.MacOS +#endif { internal class Deserializer : IDeserializer { diff --git a/Xamarin.Forms.Platform.iOS/EffectUtilities.cs b/Xamarin.Forms.Platform.iOS/EffectUtilities.cs index c9523479..6b053787 100644 --- a/Xamarin.Forms.Platform.iOS/EffectUtilities.cs +++ b/Xamarin.Forms.Platform.iOS/EffectUtilities.cs @@ -1,4 +1,10 @@ + +#if __MOBILE__ namespace Xamarin.Forms.Platform.iOS +#else + +namespace Xamarin.Forms.Platform.MacOS +#endif { internal static class EffectUtilities { diff --git a/Xamarin.Forms.Platform.iOS/ElementChangedEventArgs.cs b/Xamarin.Forms.Platform.iOS/ElementChangedEventArgs.cs index 560cfd1c..49cf85d9 100644 --- a/Xamarin.Forms.Platform.iOS/ElementChangedEventArgs.cs +++ b/Xamarin.Forms.Platform.iOS/ElementChangedEventArgs.cs @@ -1,10 +1,16 @@ using System; +#if __MOBILE__ namespace Xamarin.Forms.Platform.iOS +#else + +namespace Xamarin.Forms.Platform.MacOS +#endif { public class VisualElementChangedEventArgs : ElementChangedEventArgs<VisualElement> { - public VisualElementChangedEventArgs(VisualElement oldElement, VisualElement newElement) : base(oldElement, newElement) + public VisualElementChangedEventArgs(VisualElement oldElement, VisualElement newElement) + : base(oldElement, newElement) { } } diff --git a/Xamarin.Forms.Platform.iOS/EventTracker.cs b/Xamarin.Forms.Platform.iOS/EventTracker.cs index 9c6c90e9..596506a5 100644 --- a/Xamarin.Forms.Platform.iOS/EventTracker.cs +++ b/Xamarin.Forms.Platform.iOS/EventTracker.cs @@ -3,27 +3,42 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; + +#if __MOBILE__ using UIKit; +using NativeView = UIKit.UIView; +using NativeGestureRecognizer = UIKit.UIGestureRecognizer; +using NativeGestureRecognizerState = UIKit.UIGestureRecognizerState; namespace Xamarin.Forms.Platform.iOS +#else +using AppKit; +using NativeView = AppKit.NSView; +using NativeGestureRecognizer = AppKit.NSGestureRecognizer; +using NativeGestureRecognizerState = AppKit.NSGestureRecognizerState; + +namespace Xamarin.Forms.Platform.MacOS +#endif { public class EventTracker : IDisposable { readonly NotifyCollectionChangedEventHandler _collectionChangedHandler; - readonly Dictionary<IGestureRecognizer, UIGestureRecognizer> _gestureRecognizers = new Dictionary<IGestureRecognizer, UIGestureRecognizer>(); + readonly Dictionary<IGestureRecognizer, NativeGestureRecognizer> _gestureRecognizers = new Dictionary<IGestureRecognizer, NativeGestureRecognizer>(); readonly IVisualElementRenderer _renderer; bool _disposed; - UIView _handler; + NativeView _handler; double _previousScale = 1.0; +#if __MOBILE__ UITouchEventArgs _shouldReceive; +#endif public EventTracker(IVisualElementRenderer renderer) { if (renderer == null) - throw new ArgumentNullException("renderer"); + throw new ArgumentNullException(nameof(renderer)); _collectionChangedHandler = ModelGestureRecognizersOnCollectionChanged; @@ -62,18 +77,18 @@ namespace Xamarin.Forms.Platform.iOS _handler = null; } - public void LoadEvents(UIView handler) + public void LoadEvents(NativeView handler) { if (_disposed) throw new ObjectDisposedException(null); - +#if __MOBILE__ _shouldReceive = (r, t) => t.View is IVisualElementRenderer; - +#endif _handler = handler; OnElementChanged(this, new VisualElementChangedEventArgs(null, _renderer.Element)); } - protected virtual UIGestureRecognizer GetNativeRecognizer(IGestureRecognizer recognizer) + protected virtual NativeGestureRecognizer GetNativeRecognizer(IGestureRecognizer recognizer) { if (recognizer == null) return null; @@ -84,7 +99,7 @@ namespace Xamarin.Forms.Platform.iOS var tapRecognizer = recognizer as TapGestureRecognizer; if (tapRecognizer != null) { - var uiRecognizer = CreateTapRecognizer(1, tapRecognizer.NumberOfTapsRequired, r => + var returnAction = new Action(() => { var tapGestureRecognizer = weakRecognizer.Target as TapGestureRecognizer; var eventTracker = weakEventTracker.Target as EventTracker; @@ -93,6 +108,7 @@ namespace Xamarin.Forms.Platform.iOS if (tapGestureRecognizer != null && view != null) tapGestureRecognizer.SendTapped(view); }); + var uiRecognizer = CreateTapRecognizer(tapRecognizer.NumberOfTapsRequired, returnAction); return uiRecognizer; } @@ -110,41 +126,51 @@ namespace Xamarin.Forms.Platform.iOS { var oldScale = eventTracker._previousScale; var originPoint = r.LocationInView(null); +#if __MOBILE__ originPoint = UIApplication.SharedApplication.KeyWindow.ConvertPointToView(originPoint, eventTracker._renderer.NativeView); +#else + originPoint = NSApplication.SharedApplication.KeyWindow.ContentView.ConvertPointToView(originPoint, eventTracker._renderer.NativeView); +#endif var scaledPoint = new Point(originPoint.X / view.Width, originPoint.Y / view.Height); switch (r.State) { - case UIGestureRecognizerState.Began: + case NativeGestureRecognizerState.Began: +#if __MOBILE__ if (r.NumberOfTouches < 2) return; +#endif pinchGestureRecognizer.SendPinchStarted(view, scaledPoint); startingScale = view.Scale; break; - case UIGestureRecognizerState.Changed: + case NativeGestureRecognizerState.Changed: +#if __MOBILE__ if (r.NumberOfTouches < 2 && pinchGestureRecognizer.IsPinching) { - r.State = UIGestureRecognizerState.Ended; + r.State = NativeGestureRecognizerState.Ended; pinchGestureRecognizer.SendPinchEnded(view); return; } - + var scale = r.Scale; +#else + var scale = r.Magnification; +#endif var delta = 1.0; - var dif = Math.Abs(r.Scale - oldScale) * startingScale; - if (oldScale < r.Scale) + var dif = Math.Abs(scale - oldScale) * startingScale; + if (oldScale < scale) delta = 1 + dif; - if (oldScale > r.Scale) + if (oldScale > scale) delta = 1 - dif; pinchGestureRecognizer.SendPinch(view, delta, scaledPoint); - eventTracker._previousScale = r.Scale; + eventTracker._previousScale = scale; break; - case UIGestureRecognizerState.Cancelled: - case UIGestureRecognizerState.Failed: + case NativeGestureRecognizerState.Cancelled: + case NativeGestureRecognizerState.Failed: if (pinchGestureRecognizer.IsPinching) pinchGestureRecognizer.SendPinchCanceled(view); break; - case UIGestureRecognizerState.Ended: + case NativeGestureRecognizerState.Ended: if (pinchGestureRecognizer.IsPinching) pinchGestureRecognizer.SendPinchEnded(view); eventTracker._previousScale = 1; @@ -168,33 +194,42 @@ namespace Xamarin.Forms.Platform.iOS { switch (r.State) { - case UIGestureRecognizerState.Began: + case NativeGestureRecognizerState.Began: +#if __MOBILE__ if (r.NumberOfTouches != panRecognizer.TouchPoints) return; +#endif panGestureRecognizer.SendPanStarted(view, Application.Current.PanGestureId); break; - case UIGestureRecognizerState.Changed: + case NativeGestureRecognizerState.Changed: +#if __MOBILE__ if (r.NumberOfTouches != panRecognizer.TouchPoints) { - r.State = UIGestureRecognizerState.Ended; + r.State = NativeGestureRecognizerState.Ended; panGestureRecognizer.SendPanCompleted(view, Application.Current.PanGestureId); Application.Current.PanGestureId++; return; } +#endif var translationInView = r.TranslationInView(_handler); panGestureRecognizer.SendPan(view, translationInView.X, translationInView.Y, Application.Current.PanGestureId); break; - case UIGestureRecognizerState.Cancelled: - case UIGestureRecognizerState.Failed: + case NativeGestureRecognizerState.Cancelled: + case NativeGestureRecognizerState.Failed: panGestureRecognizer.SendPanCanceled(view, Application.Current.PanGestureId); Application.Current.PanGestureId++; break; - case UIGestureRecognizerState.Ended: + case NativeGestureRecognizerState.Ended: +#if __MOBILE__ if (r.NumberOfTouches != panRecognizer.TouchPoints) { panGestureRecognizer.SendPanCompleted(view, Application.Current.PanGestureId); Application.Current.PanGestureId++; } +#else + panGestureRecognizer.SendPanCompleted(view, Application.Current.PanGestureId); + Application.Current.PanGestureId++; +#endif break; } } @@ -204,7 +239,7 @@ namespace Xamarin.Forms.Platform.iOS return null; } - +#if __MOBILE__ UIPanGestureRecognizer CreatePanRecognizer(int numTouches, Action<UIPanGestureRecognizer> action) { var result = new UIPanGestureRecognizer(action); @@ -218,14 +253,33 @@ namespace Xamarin.Forms.Platform.iOS return result; } - UITapGestureRecognizer CreateTapRecognizer(int numFingers, int numTaps, Action<UITapGestureRecognizer> action) + UITapGestureRecognizer CreateTapRecognizer(int numTaps, Action action, int numFingers = 1) { var result = new UITapGestureRecognizer(action); result.NumberOfTouchesRequired = (uint)numFingers; result.NumberOfTapsRequired = (uint)numTaps; return result; } +#else + NSPanGestureRecognizer CreatePanRecognizer(int numTouches, Action<NSPanGestureRecognizer> action) + { + var result = new NSPanGestureRecognizer(action); + return result; + } + + NSMagnificationGestureRecognizer CreatePinchRecognizer(Action<NSMagnificationGestureRecognizer> action) + { + var result = new NSMagnificationGestureRecognizer(action); + return result; + } + NSClickGestureRecognizer CreateTapRecognizer(int numTaps, Action action) + { + var result = new NSClickGestureRecognizer(action); + result.NumberOfClicksRequired = numTaps; + return result; + } +#endif void LoadRecognizers() { if (ElementGestureRecognizers == null) @@ -239,7 +293,9 @@ namespace Xamarin.Forms.Platform.iOS var nativeRecognizer = GetNativeRecognizer(recognizer); if (nativeRecognizer != null) { +#if __MOBILE__ nativeRecognizer.ShouldReceiveTouch = _shouldReceive; +#endif _handler.AddGestureRecognizer(nativeRecognizer); _gestureRecognizers[recognizer] = nativeRecognizer; diff --git a/Xamarin.Forms.Platform.iOS/ExportRendererAttribute.cs b/Xamarin.Forms.Platform.iOS/ExportRendererAttribute.cs index 50bba17f..3b3ef91b 100644 --- a/Xamarin.Forms.Platform.iOS/ExportRendererAttribute.cs +++ b/Xamarin.Forms.Platform.iOS/ExportRendererAttribute.cs @@ -1,29 +1,37 @@ using System; + +#if __MOBILE__ using UIKit; +#endif namespace Xamarin.Forms { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public sealed class ExportRendererAttribute : HandlerAttribute { +#if __MOBILE__ public ExportRendererAttribute(Type handler, Type target, UIUserInterfaceIdiom idiom) : base(handler, target) { Idiomatic = true; Idiom = idiom; } + internal UIUserInterfaceIdiom Idiom { get; } +#endif public ExportRendererAttribute(Type handler, Type target) : base(handler, target) { Idiomatic = false; } - internal UIUserInterfaceIdiom Idiom { get; } - internal bool Idiomatic { get; } public override bool ShouldRegister() { +#if __MOBILE__ return !Idiomatic || Idiom == UIDevice.CurrentDevice.UserInterfaceIdiom; +#else + return !Idiomatic; +#endif } } }
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.iOS/Extensions/ColorExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/ColorExtensions.cs index bb4342ab..2b8b9101 100644 --- a/Xamarin.Forms.Platform.iOS/Extensions/ColorExtensions.cs +++ b/Xamarin.Forms.Platform.iOS/Extensions/ColorExtensions.cs @@ -1,16 +1,27 @@ using System; using CoreGraphics; -using UIKit; using PointF = CoreGraphics.CGPoint; using RectangleF = CoreGraphics.CGRect; using SizeF = CoreGraphics.CGSize; - +#if __MOBILE__ +using UIKit; namespace Xamarin.Forms.Platform.iOS +#else +using AppKit; +using UIColor = AppKit.NSColor; + +namespace Xamarin.Forms.Platform.MacOS +#endif { public static class ColorExtensions { +#if __MOBILE__ internal static readonly UIColor Black = UIColor.Black; internal static readonly UIColor SeventyPercentGrey = new UIColor(0.7f, 0.7f, 0.7f, 1); +#else + internal static readonly NSColor Black = NSColor.Black; + internal static readonly NSColor SeventyPercentGrey = NSColor.FromRgba(0.7f, 0.7f, 0.7f, 1); +#endif public static CGColor ToCGColor(this Color color) { @@ -23,10 +34,15 @@ namespace Xamarin.Forms.Platform.iOS nfloat green; nfloat blue; nfloat alpha; +#if __MOBILE__ color.GetRGBA(out red, out green, out blue, out alpha); +#else + color.GetRgba(out red, out green, out blue, out alpha); +#endif return new Color(red, green, blue, alpha); } +#if __MOBILE__ public static UIColor ToUIColor(this Color color) { return new UIColor((float)color.R, (float)color.G, (float)color.B, (float)color.A); @@ -47,6 +63,28 @@ namespace Xamarin.Forms.Platform.iOS return color.ToUIColor(); } +#else + public static NSColor ToNSColor(this Color color) + { + return NSColor.FromRgba((float)color.R, (float)color.G, (float)color.B, (float)color.A); + } + + public static NSColor ToNSColor(this Color color, Color defaultColor) + { + if (color.IsDefault) + return defaultColor.ToNSColor(); + + return color.ToNSColor(); + } + + public static NSColor ToNSColor(this Color color, NSColor defaultColor) + { + if (color.IsDefault) + return defaultColor; + + return color.ToNSColor(); + } +#endif } public static class PointExtensions @@ -55,6 +93,11 @@ namespace Xamarin.Forms.Platform.iOS { return new Point(point.X, point.Y); } + + public static PointF ToPointF(this Point point) + { + return new PointF(point.X, point.Y); + } } public static class SizeExtensions diff --git a/Xamarin.Forms.Platform.iOS/Extensions/DateExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/DateExtensions.cs index bb0dfff9..73ca347c 100644 --- a/Xamarin.Forms.Platform.iOS/Extensions/DateExtensions.cs +++ b/Xamarin.Forms.Platform.iOS/Extensions/DateExtensions.cs @@ -1,7 +1,12 @@ using System; using Foundation; +#if __MOBILE__ namespace Xamarin.Forms.Platform.iOS +#else + +namespace Xamarin.Forms.Platform.MacOS +#endif { public static class DateExtensions { diff --git a/Xamarin.Forms.Platform.iOS/Extensions/LayoutExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/LayoutExtensions.cs index 823c3f30..d65caf12 100644 --- a/Xamarin.Forms.Platform.iOS/Extensions/LayoutExtensions.cs +++ b/Xamarin.Forms.Platform.iOS/Extensions/LayoutExtensions.cs @@ -1,10 +1,19 @@ using System.Collections.Generic; using CoreGraphics; +#if __MOBILE__ using UIKit; - +using Xamarin.Forms.Platform.iOS; namespace Xamarin.Forms.Platform.iOS +#else +using AppKit; +using UIView = AppKit.NSView; +using Xamarin.Forms.Platform.MacOS; + +namespace Xamarin.Forms.Platform.MacOS +#endif { - public delegate SizeRequest? GetDesiredSizeDelegate(NativeViewWrapperRenderer renderer, double widthConstraint, double heightConstraint); + public delegate SizeRequest? GetDesiredSizeDelegate( + NativeViewWrapperRenderer renderer, double widthConstraint, double heightConstraint); public delegate CGSize? SizeThatFitsDelegate(CGSize size); @@ -12,13 +21,15 @@ namespace Xamarin.Forms.Platform.iOS public static class LayoutExtensions { - public static void Add(this IList<View> children, UIView view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, SizeThatFitsDelegate sizeThatFitsDelegate = null, - LayoutSubviewsDelegate layoutSubViews = null) + public static void Add(this IList<View> children, UIView view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, + SizeThatFitsDelegate sizeThatFitsDelegate = null, + LayoutSubviewsDelegate layoutSubViews = null) { children.Add(view.ToView(getDesiredSizeDelegate, sizeThatFitsDelegate, layoutSubViews)); } - public static View ToView(this UIView view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, SizeThatFitsDelegate sizeThatFitsDelegate = null, LayoutSubviewsDelegate layoutSubViews = null) + public static View ToView(this UIView view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, + SizeThatFitsDelegate sizeThatFitsDelegate = null, LayoutSubviewsDelegate layoutSubViews = null) { return new NativeViewWrapper(view, getDesiredSizeDelegate, sizeThatFitsDelegate, layoutSubViews); } diff --git a/Xamarin.Forms.Platform.iOS/Extensions/PlatformConfigurationExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/PlatformConfigurationExtensions.cs index f61837f2..f2932e3a 100644 --- a/Xamarin.Forms.Platform.iOS/Extensions/PlatformConfigurationExtensions.cs +++ b/Xamarin.Forms.Platform.iOS/Extensions/PlatformConfigurationExtensions.cs @@ -1,11 +1,18 @@ +#if __MOBILE__ +using CurrentPlatform = Xamarin.Forms.PlatformConfiguration.iOS; namespace Xamarin.Forms.Platform.iOS +#else +using CurrentPlatform = Xamarin.Forms.PlatformConfiguration.macOS; + +namespace Xamarin.Forms.Platform.MacOS +#endif { public static class PlatformConfigurationExtensions { - public static IPlatformElementConfiguration<PlatformConfiguration.iOS, T> OnThisPlatform<T>(this T element) + public static IPlatformElementConfiguration<CurrentPlatform, T> OnThisPlatform<T>(this T element) where T : Element, IElementConfiguration<T> { - return (element).On<PlatformConfiguration.iOS>(); + return (element).On<CurrentPlatform>(); } } }
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs index 4c3eed98..8248af11 100644 --- a/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs +++ b/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs @@ -2,10 +2,15 @@ using System; using System.Collections.Generic; using System.Drawing; using System.Linq; -using UIKit; using static System.String; - +#if __MOBILE__ +using UIKit; namespace Xamarin.Forms.Platform.iOS +#else +using UIView = AppKit.NSView; + +namespace Xamarin.Forms.Platform.MacOS +#endif { public static class UIViewExtensions { @@ -16,15 +21,28 @@ namespace Xamarin.Forms.Platform.iOS return self.Subviews.Concat(self.Subviews.SelectMany(s => s.Descendants())); } - public static SizeRequest GetSizeRequest(this UIView self, double widthConstraint, double heightConstraint, double minimumWidth = -1, double minimumHeight = -1) + public static SizeRequest GetSizeRequest(this UIView self, double widthConstraint, double heightConstraint, + double minimumWidth = -1, double minimumHeight = -1) { - var s = self.SizeThatFits(new SizeF((float)widthConstraint, (float)heightConstraint)); - var request = new Size(s.Width == float.PositiveInfinity ? double.PositiveInfinity : s.Width, s.Height == float.PositiveInfinity ? double.PositiveInfinity : s.Height); - var minimum = new Size(minimumWidth < 0 ? request.Width : minimumWidth, minimumHeight < 0 ? request.Height : minimumHeight); + CoreGraphics.CGSize s; +#if __MOBILE__ + s = self.SizeThatFits(new SizeF((float)widthConstraint, (float)heightConstraint)); +#else + var control = self as AppKit.NSControl; + if (control != null) + s = control.SizeThatFits(new CoreGraphics.CGSize(widthConstraint, heightConstraint)); + else + s = self.FittingSize; +#endif + var request = new Size(s.Width == float.PositiveInfinity ? double.PositiveInfinity : s.Width, + s.Height == float.PositiveInfinity ? double.PositiveInfinity : s.Height); + var minimum = new Size(minimumWidth < 0 ? request.Width : minimumWidth, + minimumHeight < 0 ? request.Height : minimumHeight); return new SizeRequest(request, minimum); } - public static void SetBinding(this UIView view, string propertyName, BindingBase bindingBase, string updateSourceEventName = null) + public static void SetBinding(this UIView view, string propertyName, BindingBase bindingBase, + string updateSourceEventName = null) { var binding = bindingBase as Binding; //This will allow setting bindings from Xaml by reusing the MarkupExtension @@ -51,6 +69,7 @@ namespace Xamarin.Forms.Platform.iOS view.AddObserver(nativePropertyListener, key, Foundation.NSKeyValueObservingOptions.New, IntPtr.Zero); } } +#if __MOBILE__ catch (Foundation.MonoTouchException ex) { nativePropertyListener = null; @@ -61,7 +80,12 @@ namespace Xamarin.Forms.Platform.iOS } throw ex; } - +#else + catch (Exception ex) + { + throw ex; + } +#endif } NativeBindingHelpers.SetBinding(view, propertyName, bindingBase, nativePropertyListener); @@ -77,7 +101,8 @@ namespace Xamarin.Forms.Platform.iOS NativeBindingHelpers.SetValue(target, targetProperty, value); } - public static void SetBindingContext(this UIView target, object bindingContext, Func<UIView, IEnumerable<UIView>> getChildren = null) + public static void SetBindingContext(this UIView target, object bindingContext, + Func<UIView, IEnumerable<UIView>> getChildren = null) { NativeBindingHelpers.SetBindingContext(target, bindingContext, getChildren); } @@ -107,6 +132,7 @@ namespace Xamarin.Forms.Platform.iOS return null; } +#if __MOBILE__ internal static UIView FindFirstResponder(this UIView view) { if (view.IsFirstResponder) @@ -121,5 +147,6 @@ namespace Xamarin.Forms.Platform.iOS return null; } +#endif } }
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.iOS/Forms.cs b/Xamarin.Forms.Platform.iOS/Forms.cs index 2c8fc6f7..d6e7e07f 100644 --- a/Xamarin.Forms.Platform.iOS/Forms.cs +++ b/Xamarin.Forms.Platform.iOS/Forms.cs @@ -11,11 +11,18 @@ using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; -using CoreFoundation; +using Xamarin.Forms.Internals; using Foundation; +#if __MOBILE__ using UIKit; -using Xamarin.Forms.Internals; using Xamarin.Forms.Platform.iOS; +using TNativeView = UIKit.UIView; +#else +using AppKit; +using Xamarin.Forms.Platform.MacOS; +using TNativeView = AppKit.NSView; + +#endif namespace Xamarin.Forms { @@ -24,7 +31,11 @@ namespace Xamarin.Forms //Preserve GetCallingAssembly static readonly bool nevertrue = false; + public static bool IsInitialized { get; private set; } + +#if __MOBILE__ static bool? s_isiOS9OrNewer; +#endif static Forms() { @@ -32,8 +43,7 @@ namespace Xamarin.Forms Assembly.GetCallingAssembly(); } - public static bool IsInitialized { get; private set; } - +#if __MOBILE__ internal static bool IsiOS9OrNewer { get @@ -43,6 +53,7 @@ namespace Xamarin.Forms return s_isiOS9OrNewer.Value; } } +#endif public static void Init() { @@ -53,19 +64,22 @@ namespace Xamarin.Forms Log.Listeners.Add(new DelegateLogListener((c, m) => Trace.WriteLine(m, c))); +#if __MOBILE__ + Device.Idiom = UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad ? TargetIdiom.Tablet : TargetIdiom.Phone; +#else + Device.Idiom = TargetIdiom.Desktop; +#endif Device.PlatformServices = new IOSPlatformServices(); Device.Info = new IOSDeviceInfo(); - Registrar.RegisterAll(new[] { typeof(ExportRendererAttribute), typeof(ExportCellAttribute), typeof(ExportImageSourceHandlerAttribute) }); - - Device.Idiom = UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad ? TargetIdiom.Tablet : TargetIdiom.Phone; - + Registrar.RegisterAll(new[] + { typeof(ExportRendererAttribute), typeof(ExportCellAttribute), typeof(ExportImageSourceHandlerAttribute) }); ExpressionSearch.Default = new iOSExpressionSearch(); } public static event EventHandler<ViewInitializedEventArgs> ViewInitialized; - internal static void SendViewInitialized(this VisualElement self, UIView nativeView) + internal static void SendViewInitialized(this VisualElement self, TNativeView nativeView) { ViewInitialized?.Invoke(self, new ViewInitializedEventArgs { View = self, NativeView = nativeView }); } @@ -99,16 +113,22 @@ namespace Xamarin.Forms internal class IOSDeviceInfo : DeviceInfo { +#if __MOBILE__ readonly NSObject _notification; +#endif readonly Size _scaledScreenSize; readonly double _scalingFactor; public IOSDeviceInfo() { +#if __MOBILE__ _notification = UIDevice.Notifications.ObserveOrientationDidChange((sender, args) => CurrentOrientation = UIDevice.CurrentDevice.Orientation.ToDeviceOrientation()); - _scalingFactor = UIScreen.MainScreen.Scale; _scaledScreenSize = new Size(UIScreen.MainScreen.Bounds.Width, UIScreen.MainScreen.Bounds.Height); +#else + _scalingFactor = NSScreen.MainScreen.BackingScaleFactor; + _scaledScreenSize = new Size(NSScreen.MainScreen.Frame.Width, NSScreen.MainScreen.Frame.Height); +#endif PixelScreenSize = new Size(_scaledScreenSize.Width * _scalingFactor, _scaledScreenSize.Height * _scalingFactor); } @@ -120,7 +140,9 @@ namespace Xamarin.Forms protected override void Dispose(bool disposing) { +#if __MOBILE__ _notification.Dispose(); +#endif base.Dispose(disposing); } } @@ -198,11 +220,19 @@ namespace Xamarin.Forms public bool IsInvokeRequired => !NSThread.IsMain; +#if __MOBILE__ public string RuntimePlatform => Device.iOS; +#else + public string RuntimePlatform => Device.macOS; +#endif public void OpenUriAction(Uri uri) { +#if __MOBILE__ UIApplication.SharedApplication.OpenUrl(new NSUrl(uri.AbsoluteUri)); +#else + NSWorkspace.SharedWorkspace.OpenUrl(new NSUrl(uri.AbsoluteUri)); +#endif } public void StartTimer(TimeSpan interval, Func<bool> callback) @@ -217,11 +247,11 @@ namespace Xamarin.Forms HttpClient GetHttpClient() { - var proxy = CFNetwork.GetSystemProxySettings(); + var proxy = CoreFoundation.CFNetwork.GetSystemProxySettings(); var handler = new HttpClientHandler(); if (!string.IsNullOrEmpty(proxy.HTTPProxy)) { - handler.Proxy = CFNetwork.GetDefaultProxy(); + handler.Proxy = CoreFoundation.CFNetwork.GetDefaultProxy(); handler.UseProxy = true; } return new HttpClient(handler); @@ -272,7 +302,8 @@ namespace Xamarin.Forms public Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access, FileShare share) { - Stream stream = _isolatedStorageFile.OpenFile(path, (System.IO.FileMode)mode, (System.IO.FileAccess)access, (System.IO.FileShare)share); + Stream stream = _isolatedStorageFile.OpenFile(path, (System.IO.FileMode)mode, (System.IO.FileAccess)access, + (System.IO.FileShare)share); return Task.FromResult(stream); } } diff --git a/Xamarin.Forms.Platform.iOS/IVisualElementRenderer.cs b/Xamarin.Forms.Platform.iOS/IVisualElementRenderer.cs index 9a2bf580..ffb2de29 100644 --- a/Xamarin.Forms.Platform.iOS/IVisualElementRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/IVisualElementRenderer.cs @@ -1,15 +1,24 @@ using System; +#if __MOBILE__ using UIKit; +using NativeView = UIKit.UIView; +using NativeViewController = UIKit.UIViewController; namespace Xamarin.Forms.Platform.iOS +#else +using NativeView = AppKit.NSView; +using NativeViewController = AppKit.NSViewController; + +namespace Xamarin.Forms.Platform.MacOS +#endif { public interface IVisualElementRenderer : IDisposable, IRegisterable { VisualElement Element { get; } - UIView NativeView { get; } + NativeView NativeView { get; } - UIViewController ViewController { get; } + NativeViewController ViewController { get; } event EventHandler<VisualElementChangedEventArgs> ElementChanged; diff --git a/Xamarin.Forms.Platform.iOS/NativeValueConverterService.cs b/Xamarin.Forms.Platform.iOS/NativeValueConverterService.cs index 9e20e045..acdd6523 100644 --- a/Xamarin.Forms.Platform.iOS/NativeValueConverterService.cs +++ b/Xamarin.Forms.Platform.iOS/NativeValueConverterService.cs @@ -1,16 +1,23 @@ using System; +#if __MOBILE__ using UIKit; - [assembly: Xamarin.Forms.Dependency(typeof(Xamarin.Forms.Platform.iOS.NativeValueConverterService))] - namespace Xamarin.Forms.Platform.iOS +#else +using UIView = AppKit.NSView; + +[assembly: Xamarin.Forms.Dependency(typeof(Xamarin.Forms.Platform.MacOS.NativeValueConverterService))] + +namespace Xamarin.Forms.Platform.MacOS +#endif { class NativeValueConverterService : Xaml.INativeValueConverterService { public bool ConvertTo(object value, Type toType, out object nativeValue) { nativeValue = null; - if (typeof(UIView).IsInstanceOfType(value) && toType.IsAssignableFrom(typeof(View))) { + if (typeof(UIView).IsInstanceOfType(value) && toType.IsAssignableFrom(typeof(View))) + { nativeValue = ((UIView)value).ToView(); return true; } diff --git a/Xamarin.Forms.Platform.iOS/NativeViewPropertyListener.cs b/Xamarin.Forms.Platform.iOS/NativeViewPropertyListener.cs index 4e6601ef..e819519a 100644 --- a/Xamarin.Forms.Platform.iOS/NativeViewPropertyListener.cs +++ b/Xamarin.Forms.Platform.iOS/NativeViewPropertyListener.cs @@ -2,7 +2,12 @@ using System; using System.ComponentModel; using Foundation; +#if __MOBILE__ namespace Xamarin.Forms.Platform.iOS +#else + +namespace Xamarin.Forms.Platform.MacOS +#endif { class NativeViewPropertyListener : NSObject, INotifyPropertyChanged { @@ -23,4 +28,4 @@ namespace Xamarin.Forms.Platform.iOS base.ObserveValue(keyPath, ofObject, change, context); } } -} +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.iOS/NativeViewWrapper.cs b/Xamarin.Forms.Platform.iOS/NativeViewWrapper.cs index 31cb186d..165bc0f9 100644 --- a/Xamarin.Forms.Platform.iOS/NativeViewWrapper.cs +++ b/Xamarin.Forms.Platform.iOS/NativeViewWrapper.cs @@ -1,10 +1,16 @@ -using UIKit; - +#if __MOBILE__ +using UIKit; namespace Xamarin.Forms.Platform.iOS +#else +using UIView = AppKit.NSView; + +namespace Xamarin.Forms.Platform.MacOS +#endif { public class NativeViewWrapper : View { - public NativeViewWrapper(UIView nativeView, GetDesiredSizeDelegate getDesiredSizeDelegate = null, SizeThatFitsDelegate sizeThatFitsDelegate = null, LayoutSubviewsDelegate layoutSubViews = null) + public NativeViewWrapper(UIView nativeView, GetDesiredSizeDelegate getDesiredSizeDelegate = null, + SizeThatFitsDelegate sizeThatFitsDelegate = null, LayoutSubviewsDelegate layoutSubViews = null) { GetDesiredSizeDelegate = getDesiredSizeDelegate; SizeThatFitsDelegate = sizeThatFitsDelegate; diff --git a/Xamarin.Forms.Platform.iOS/NativeViewWrapperRenderer.cs b/Xamarin.Forms.Platform.iOS/NativeViewWrapperRenderer.cs index 4d1252ee..cde9fe81 100644 --- a/Xamarin.Forms.Platform.iOS/NativeViewWrapperRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/NativeViewWrapperRenderer.cs @@ -1,8 +1,13 @@ using CoreGraphics; -using UIKit; using Xamarin.Forms.Internals; - +#if __MOBILE__ +using UIKit; namespace Xamarin.Forms.Platform.iOS +#else +using UIView = AppKit.NSView; + +namespace Xamarin.Forms.Platform.MacOS +#endif { public class NativeViewWrapperRenderer : ViewRenderer<NativeViewWrapper, UIView> { @@ -19,6 +24,7 @@ namespace Xamarin.Forms.Platform.iOS return result ?? base.GetDesiredSize(widthConstraint, heightConstraint); } +#if __MOBILE__ public override void LayoutSubviews() { if (Element?.LayoutSubViews == null) @@ -50,6 +56,26 @@ namespace Xamarin.Forms.Platform.iOS // if it returns null, fall back to the default implementation return result ?? base.SizeThatFits(size); } +#else + public override void Layout() + { + if (Element?.LayoutSubViews == null) + { + ((IVisualElementController)Element)?.InvalidateMeasure(InvalidationTrigger.MeasureChanged); + base.Layout(); + return; + } + + // The user has specified a different implementation of LayoutSubviews + var handled = Element.LayoutSubViews(); + + if (!handled) + { + // If the delegate wasn't able to handle the request, fall back to the default implementation + base.Layout(); + } + } +#endif protected override void OnElementChanged(ElementChangedEventArgs<NativeViewWrapper> e) { diff --git a/Xamarin.Forms.Platform.iOS/PlatformEffect.cs b/Xamarin.Forms.Platform.iOS/PlatformEffect.cs index 8fb4f975..6a1ca494 100644 --- a/Xamarin.Forms.Platform.iOS/PlatformEffect.cs +++ b/Xamarin.Forms.Platform.iOS/PlatformEffect.cs @@ -1,6 +1,11 @@ -using UIKit; - +#if __MOBILE__ +using UIKit; namespace Xamarin.Forms.Platform.iOS +#else +using UIView = AppKit.NSView; + +namespace Xamarin.Forms.Platform.MacOS +#endif { public abstract class PlatformEffect : PlatformEffect<UIView, UIView> { diff --git a/Xamarin.Forms.Platform.iOS/RendererPool.cs b/Xamarin.Forms.Platform.iOS/RendererPool.cs index babfa7bc..38fe3c02 100644 --- a/Xamarin.Forms.Platform.iOS/RendererPool.cs +++ b/Xamarin.Forms.Platform.iOS/RendererPool.cs @@ -1,11 +1,17 @@ using System; using System.Collections.Generic; +#if __MOBILE__ namespace Xamarin.Forms.Platform.iOS +#else + +namespace Xamarin.Forms.Platform.MacOS +#endif { public sealed class RendererPool { - readonly Dictionary<Type, Stack<IVisualElementRenderer>> _freeRenderers = new Dictionary<Type, Stack<IVisualElementRenderer>>(); + readonly Dictionary<Type, Stack<IVisualElementRenderer>> _freeRenderers = + new Dictionary<Type, Stack<IVisualElementRenderer>>(); readonly VisualElement _oldElement; diff --git a/Xamarin.Forms.Platform.iOS/Renderers/FontExtensions.cs b/Xamarin.Forms.Platform.iOS/Renderers/FontExtensions.cs index cbc2e625..ba8acbe5 100644 --- a/Xamarin.Forms.Platform.iOS/Renderers/FontExtensions.cs +++ b/Xamarin.Forms.Platform.iOS/Renderers/FontExtensions.cs @@ -1,15 +1,26 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using Xamarin.Forms; +#if __MOBILE__ using UIKit; - namespace Xamarin.Forms.Platform.iOS +#else +using AppKit; +using UIFont = AppKit.NSFont; + +namespace Xamarin.Forms.Platform.MacOS +#endif { public static class FontExtensions { static readonly Dictionary<ToUIFontKey, UIFont> ToUiFont = new Dictionary<ToUIFontKey, UIFont>(); - +#if __MOBILE__ public static UIFont ToUIFont(this Font self) + +#else + public static UIFont ToNSFont(this Font self) +#endif { var size = (float)self.FontSize; if (self.UseNamedSize) @@ -41,6 +52,7 @@ namespace Xamarin.Forms.Platform.iOS { try { +#if __MOBILE__ if (UIFont.FamilyNames.Contains(self.FontFamily)) { var descriptor = new UIFontDescriptor().CreateWithFamily(self.FontFamily); @@ -59,6 +71,25 @@ namespace Xamarin.Forms.Platform.iOS } return UIFont.FromName(self.FontFamily, size); + +#else + + var descriptor = new NSFontDescriptor().FontDescriptorWithFamily(self.FontFamily); + + if (bold || italic) + { + var traits = (NSFontSymbolicTraits)0; + if (bold) + traits = traits | NSFontSymbolicTraits.BoldTrait; + if (italic) + traits = traits | NSFontSymbolicTraits.ItalicTrait; + + descriptor = descriptor.FontDescriptorWithSymbolicTraits(traits); + return NSFont.FromDescription(descriptor, size); + } + + return NSFont.FromFontName(self.FontFamily, size); +#endif } catch { @@ -68,28 +99,54 @@ namespace Xamarin.Forms.Platform.iOS if (bold && italic) { var defaultFont = UIFont.SystemFontOfSize(size); +#if __MOBILE__ var descriptor = defaultFont.FontDescriptor.CreateWithTraits(UIFontDescriptorSymbolicTraits.Bold | UIFontDescriptorSymbolicTraits.Italic); return UIFont.FromDescriptor(descriptor, 0); } - if (bold) - return UIFont.BoldSystemFontOfSize(size); if (italic) return UIFont.ItalicSystemFontOfSize(size); +#else + var descriptor = defaultFont.FontDescriptor.FontDescriptorWithSymbolicTraits( + NSFontSymbolicTraits.BoldTrait | + NSFontSymbolicTraits.ItalicTrait); + + return NSFont.FromDescription(descriptor, 0); + } + if (italic) + { + Debug.WriteLine("Italic font requested, passing regular one"); + return NSFont.UserFontOfSize(size); + } +#endif + + if (bold) + return UIFont.BoldSystemFontOfSize(size); + return UIFont.SystemFontOfSize(size); } internal static bool IsDefault(this Span self) { - return self.FontFamily == null && self.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Label), true) && self.FontAttributes == FontAttributes.None; + return self.FontFamily == null && self.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Label), true) && + self.FontAttributes == FontAttributes.None; } +#if __MOBILE__ internal static UIFont ToUIFont(this Label label) +#else + internal static UIFont ToNSFont(this Label label) +#endif { var values = label.GetValues(Label.FontFamilyProperty, Label.FontSizeProperty, Label.FontAttributesProperty); - return ToUIFont((string)values[0], (float)(double)values[1], (FontAttributes)values[2]) ?? UIFont.SystemFontOfSize(UIFont.LabelFontSize); + return ToUIFont((string)values[0], (float)(double)values[1], (FontAttributes)values[2]) ?? + UIFont.SystemFontOfSize(UIFont.LabelFontSize); } +#if __MOBILE__ internal static UIFont ToUIFont(this IFontElement element) +#else + internal static NSFont ToNSFont(this IFontElement element) +#endif { return ToUIFont(element.FontFamily, (float)element.FontSize, element.FontAttributes); } @@ -104,6 +161,7 @@ namespace Xamarin.Forms.Platform.iOS try { UIFont result; +#if __MOBILE__ if (UIFont.FamilyNames.Contains(family)) { var descriptor = new UIFontDescriptor().CreateWithFamily(family); @@ -124,6 +182,26 @@ namespace Xamarin.Forms.Platform.iOS } result = UIFont.FromName(family, size); +#else + + var descriptor = new NSFontDescriptor().FontDescriptorWithFamily(family); + + if (bold || italic) + { + var traits = (NSFontSymbolicTraits)0; + if (bold) + traits = traits | NSFontSymbolicTraits.BoldTrait; + if (italic) + traits = traits | NSFontSymbolicTraits.ItalicTrait; + + descriptor = descriptor.FontDescriptorWithSymbolicTraits(traits); + result = NSFont.FromDescription(descriptor, size); + if (result != null) + return result; + } + + result = NSFont.FromFontName(family, size); +#endif if (result != null) return result; } @@ -137,13 +215,27 @@ namespace Xamarin.Forms.Platform.iOS { var defaultFont = UIFont.SystemFontOfSize(size); +#if __MOBILE__ var descriptor = defaultFont.FontDescriptor.CreateWithTraits(UIFontDescriptorSymbolicTraits.Bold | UIFontDescriptorSymbolicTraits.Italic); return UIFont.FromDescriptor(descriptor, 0); } - if (bold) - return UIFont.BoldSystemFontOfSize(size); if (italic) return UIFont.ItalicSystemFontOfSize(size); +#else + var descriptor = defaultFont.FontDescriptor.FontDescriptorWithSymbolicTraits( + NSFontSymbolicTraits.BoldTrait | + NSFontSymbolicTraits.ItalicTrait); + + return NSFont.FromDescription(descriptor, 0); + } + if (italic) + { + Debug.WriteLine("Italic font requested, passing regular one"); + return NSFont.UserFontOfSize(size); + } +#endif + if (bold) + return UIFont.BoldSystemFontOfSize(size); return UIFont.SystemFontOfSize(size); } diff --git a/Xamarin.Forms.Platform.iOS/Renderers/FormattedStringExtensions.cs b/Xamarin.Forms.Platform.iOS/Renderers/FormattedStringExtensions.cs index dce86b98..825a20bd 100644 --- a/Xamarin.Forms.Platform.iOS/Renderers/FormattedStringExtensions.cs +++ b/Xamarin.Forms.Platform.iOS/Renderers/FormattedStringExtensions.cs @@ -1,7 +1,13 @@ using Foundation; +#if __MOBILE__ using UIKit; - namespace Xamarin.Forms.Platform.iOS +#else +using AppKit; +using UIColor = AppKit.NSColor; + +namespace Xamarin.Forms.Platform.MacOS +#endif { public static class FormattedStringExtensions { @@ -19,10 +25,16 @@ namespace Xamarin.Forms.Platform.iOS if (fgcolor.IsDefault) fgcolor = Color.Black; // as defined by apple docs +#if __MOBILE__ return new NSAttributedString(span.Text, font == Font.Default ? null : font.ToUIFont(), fgcolor.ToUIColor(), span.BackgroundColor.ToUIColor()); +#else + return new NSAttributedString(span.Text, font == Font.Default ? null : font.ToNSFont(), fgcolor.ToNSColor(), + span.BackgroundColor.ToNSColor()); +#endif } - public static NSAttributedString ToAttributed(this FormattedString formattedString, Font defaultFont, Color defaultForegroundColor) + public static NSAttributedString ToAttributed(this FormattedString formattedString, Font defaultFont, + Color defaultForegroundColor) { if (formattedString == null) return null; @@ -43,6 +55,7 @@ namespace Xamarin.Forms.Platform.iOS if (span == null) return null; +#if __MOBILE__ UIFont targetFont; if (span.IsDefault()) targetFont = ((IFontElement)owner).ToUIFont(); @@ -56,9 +69,25 @@ namespace Xamarin.Forms.Platform.iOS fgcolor = Color.Black; // as defined by apple docs return new NSAttributedString(span.Text, targetFont, fgcolor.ToUIColor(), span.BackgroundColor.ToUIColor()); +#else + NSFont targetFont; + if (span.IsDefault()) + targetFont = ((IFontElement)owner).ToNSFont(); + else + targetFont = span.ToNSFont(); + + var fgcolor = span.ForegroundColor; + if (fgcolor.IsDefault) + fgcolor = defaultForegroundColor; + if (fgcolor.IsDefault) + fgcolor = Color.Black; // as defined by apple docs + + return new NSAttributedString(span.Text, targetFont, fgcolor.ToNSColor(), span.BackgroundColor.ToNSColor()); +#endif } - internal static NSAttributedString ToAttributed(this FormattedString formattedString, Element owner, Color defaultForegroundColor) + internal static NSAttributedString ToAttributed(this FormattedString formattedString, Element owner, + Color defaultForegroundColor) { if (formattedString == null) return null; diff --git a/Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs index 58312f8a..5fde3519 100644 --- a/Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs @@ -1,12 +1,21 @@ using System; using System.ComponentModel; -using UIKit; using RectangleF = CoreGraphics.CGRect; using SizeF = CoreGraphics.CGSize; +#if __MOBILE__ +using UIKit; +using NativeLabel = UIKit.UILabel; + namespace Xamarin.Forms.Platform.iOS +#else +using AppKit; +using NativeLabel = AppKit.NSTextField; + +namespace Xamarin.Forms.Platform.MacOS +#endif { - public class LabelRenderer : ViewRenderer<Label, UILabel> + public class LabelRenderer : ViewRenderer<Label, NativeLabel> { SizeRequest _perfectSize; @@ -35,9 +44,16 @@ namespace Xamarin.Forms.Platform.iOS return result; } +#if __MOBILE__ public override void LayoutSubviews() { base.LayoutSubviews(); +#else + public override void Layout() + { + base.Layout(); +#endif + if (Control == null) return; @@ -69,7 +85,12 @@ namespace Xamarin.Forms.Platform.iOS { if (Control == null) { - SetNativeControl(new UILabel(RectangleF.Empty) { BackgroundColor = UIColor.Clear }); + SetNativeControl(new NativeLabel(RectangleF.Empty)); +#if !__MOBILE__ + Control.Editable = false; + Control.Bezeled = false; + Control.DrawsBackground = false; +#endif } UpdateText(); @@ -87,7 +108,7 @@ namespace Xamarin.Forms.Platform.iOS if (e.PropertyName == Label.HorizontalTextAlignmentProperty.PropertyName) UpdateAlignment(); else if (e.PropertyName == Label.VerticalTextAlignmentProperty.PropertyName) - LayoutSubviews(); + UpdateLayout(); else if (e.PropertyName == Label.TextColorProperty.PropertyName) UpdateText(); else if (e.PropertyName == Label.FontProperty.PropertyName) @@ -102,21 +123,33 @@ namespace Xamarin.Forms.Platform.iOS protected override void SetBackgroundColor(Color color) { +#if __MOBILE__ if (color == Color.Default) BackgroundColor = UIColor.Clear; else BackgroundColor = color.ToUIColor(); +#else + if (color == Color.Default) + Layer.BackgroundColor = NSColor.Clear.CGColor; + else + Layer.BackgroundColor = color.ToCGColor(); +#endif + } void UpdateAlignment() { +#if __MOBILE__ Control.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment(); +#else + Control.Alignment = Element.HorizontalTextAlignment.ToNativeTextAlignment(); +#endif } void UpdateLineBreakMode() { _perfectSizeValid = false; - +#if __MOBILE__ switch (Element.LineBreakMode) { case LineBreakMode.NoWrap: @@ -144,6 +177,35 @@ namespace Xamarin.Forms.Platform.iOS Control.Lines = 1; break; } +#else + switch (Element.LineBreakMode) + { + case LineBreakMode.NoWrap: + Control.LineBreakMode = NSLineBreakMode.Clipping; + Control.MaximumNumberOfLines = 1; + break; + case LineBreakMode.WordWrap: + Control.LineBreakMode = NSLineBreakMode.ByWordWrapping; + Control.MaximumNumberOfLines = 0; + break; + case LineBreakMode.CharacterWrap: + Control.LineBreakMode = NSLineBreakMode.CharWrapping; + Control.MaximumNumberOfLines = 0; + break; + case LineBreakMode.HeadTruncation: + Control.LineBreakMode = NSLineBreakMode.TruncatingHead; + Control.MaximumNumberOfLines = 1; + break; + case LineBreakMode.MiddleTruncation: + Control.LineBreakMode = NSLineBreakMode.TruncatingMiddle; + Control.MaximumNumberOfLines = 1; + break; + case LineBreakMode.TailTruncation: + Control.LineBreakMode = NSLineBreakMode.TruncatingTail; + Control.MaximumNumberOfLines = 1; + break; + } +#endif } void UpdateText() @@ -151,9 +213,12 @@ namespace Xamarin.Forms.Platform.iOS _perfectSizeValid = false; var values = Element.GetValues(Label.FormattedTextProperty, Label.TextProperty, Label.TextColorProperty); - var formatted = (FormattedString)values[0]; + var formatted = values[0] as FormattedString; if (formatted != null) + { +#if __MOBILE__ Control.AttributedText = formatted.ToAttributed(Element, (Color)values[2]); + } else { Control.Text = (string)values[1]; @@ -161,8 +226,28 @@ namespace Xamarin.Forms.Platform.iOS Control.Font = Element.ToUIFont(); Control.TextColor = ((Color)values[2]).ToUIColor(ColorExtensions.Black); } +#else + Control.AttributedStringValue = formatted.ToAttributed(Element, (Color)values[2]); + } + else + { + Control.StringValue = (string)values[1] ?? ""; + // default value of color documented to be black in iOS docs + Control.Font = Element.ToNSFont(); + Control.TextColor = ((Color)values[2]).ToNSColor(ColorExtensions.Black); + } +#endif + + UpdateLayout(); + } + void UpdateLayout() + { +#if __MOBILE__ LayoutSubviews(); +#else + Layout(); +#endif } } }
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.iOS/ResourcesProvider.cs b/Xamarin.Forms.Platform.iOS/ResourcesProvider.cs index 3e5655c9..f02655a0 100644 --- a/Xamarin.Forms.Platform.iOS/ResourcesProvider.cs +++ b/Xamarin.Forms.Platform.iOS/ResourcesProvider.cs @@ -1,6 +1,11 @@ +#if __MOBILE__ using UIKit; namespace Xamarin.Forms.Platform.iOS +#else + +namespace Xamarin.Forms.Platform.MacOS +#endif { internal class ResourcesProvider : ISystemResourcesProvider { @@ -8,7 +13,9 @@ namespace Xamarin.Forms.Platform.iOS public ResourcesProvider() { +#if __MOBILE__ UIApplication.Notifications.ObserveContentSizeCategoryChanged((sender, args) => UpdateStyles()); +#endif } public IResourceDictionary GetSystemResources() @@ -19,6 +26,7 @@ namespace Xamarin.Forms.Platform.iOS return _dictionary; } +#if __MOBILE__ Style GenerateListItemDetailTextStyle() { var font = new UITableViewCell(UITableViewCellStyle.Subtitle, "Foobar").DetailTextLabel.Font; @@ -44,7 +52,7 @@ namespace Xamarin.Forms.Platform.iOS void UpdateStyles() { - + _dictionary[Device.Styles.TitleStyleKey] = GenerateStyle(UIFont.PreferredHeadline); _dictionary[Device.Styles.SubtitleStyleKey] = GenerateStyle(UIFont.PreferredSubheadline); _dictionary[Device.Styles.BodyStyleKey] = GenerateStyle(UIFont.PreferredBody); @@ -53,5 +61,11 @@ namespace Xamarin.Forms.Platform.iOS _dictionary[Device.Styles.ListItemTextStyleKey] = GenerateListItemTextStyle(); _dictionary[Device.Styles.ListItemDetailTextStyleKey] = GenerateListItemDetailTextStyle(); } +#else + void UpdateStyles() + { + } +#endif + } }
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.iOS/ViewInitializedEventArgs.cs b/Xamarin.Forms.Platform.iOS/ViewInitializedEventArgs.cs index 73041163..9ee0da88 100644 --- a/Xamarin.Forms.Platform.iOS/ViewInitializedEventArgs.cs +++ b/Xamarin.Forms.Platform.iOS/ViewInitializedEventArgs.cs @@ -1,11 +1,16 @@ using System; -using UIKit; +#if __MOBILE__ +using TNativeView = UIKit.UIView; +#else +using TNativeView = AppKit.NSView; + +#endif namespace Xamarin.Forms { public class ViewInitializedEventArgs : EventArgs { - public UIView NativeView { get; internal set; } + public TNativeView NativeView { get; internal set; } public VisualElement View { get; internal set; } } diff --git a/Xamarin.Forms.Platform.iOS/ViewRenderer.cs b/Xamarin.Forms.Platform.iOS/ViewRenderer.cs index 6ecc307b..01f8e06a 100644 --- a/Xamarin.Forms.Platform.iOS/ViewRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/ViewRenderer.cs @@ -1,21 +1,34 @@ using System; using System.ComponentModel; -using UIKit; + using RectangleF = CoreGraphics.CGRect; using SizeF = CoreGraphics.CGSize; +#if __MOBILE__ +using UIKit; +using NativeView = UIKit.UIView; +using NativeColor = UIKit.UIColor; +using NativeControl = UIKit.UIControl; + namespace Xamarin.Forms.Platform.iOS +#else +using NativeView = AppKit.NSView; +using NativeColor = CoreGraphics.CGColor; +using NativeControl = AppKit.NSControl; + +namespace Xamarin.Forms.Platform.MacOS +#endif { - public abstract class ViewRenderer : ViewRenderer<View, UIView> + public abstract class ViewRenderer : ViewRenderer<View, NativeView> { } - public abstract class ViewRenderer<TView, TNativeView> : VisualElementRenderer<TView> where TView : View where TNativeView : UIView + public abstract class ViewRenderer<TView, TNativeView> : VisualElementRenderer<TView> where TView : View where TNativeView : NativeView { - UIColor _defaultColor; + NativeColor _defaultColor; public TNativeView Control { get; private set; } - +#if __MOBILE__ public override void LayoutSubviews() { base.LayoutSubviews(); @@ -30,6 +43,19 @@ namespace Xamarin.Forms.Platform.iOS return Control.SizeThatFits(size); } +#else + public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) + { + return (Control ?? NativeView).GetSizeRequest(widthConstraint, heightConstraint); + } + + public override void Layout() + { + if (Control != null) + Control.Frame = new RectangleF(0, 0, (nfloat)Element.Width, (nfloat)Element.Height); + base.Layout(); + } +#endif /// <summary> /// Determines whether the native control is disposed of when this renderer is disposed @@ -100,16 +126,24 @@ namespace Xamarin.Forms.Platform.iOS { if (Control == null) return; - +#if __MOBILE__ if (color == Color.Default) Control.BackgroundColor = _defaultColor; else Control.BackgroundColor = color.ToUIColor(); +#else + Control.Layer.BackgroundColor = color == Color.Default ? _defaultColor : color.ToCGColor(); +#endif } protected void SetNativeControl(TNativeView uiview) { +#if __MOBILE__ _defaultColor = uiview.BackgroundColor; +#else + uiview.WantsLayer = true; + _defaultColor = uiview.Layer.BackgroundColor; +#endif Control = uiview; if (Element.BackgroundColor != Color.Default) @@ -120,17 +154,19 @@ namespace Xamarin.Forms.Platform.iOS AddSubview(uiview); } - internal override void SendVisualElementInitialized(VisualElement element, UIView nativeView) +#if __MOBILE__ + internal override void SendVisualElementInitialized(VisualElement element, NativeView nativeView) { base.SendVisualElementInitialized(element, Control); } +#endif void UpdateIsEnabled() { if (Element == null || Control == null) return; - var uiControl = Control as UIControl; + var uiControl = Control as NativeControl; if (uiControl == null) return; uiControl.Enabled = Element.IsEnabled; diff --git a/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs b/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs index 1670176d..fa91cf6a 100644 --- a/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs +++ b/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs @@ -1,6 +1,11 @@ using System; +#if __MOBILE__ namespace Xamarin.Forms.Platform.iOS +#else + +namespace Xamarin.Forms.Platform.MacOS +#endif { public class VisualElementPackager : IDisposable { @@ -13,7 +18,7 @@ namespace Xamarin.Forms.Platform.iOS public VisualElementPackager(IVisualElementRenderer renderer) { if (renderer == null) - throw new ArgumentNullException("renderer"); + throw new ArgumentNullException(nameof(renderer)); Renderer = renderer; renderer.ElementChanged += OnRendererElementChanged; @@ -100,8 +105,9 @@ namespace Xamarin.Forms.Platform.iOS continue; var nativeControl = childRenderer.NativeView; - +#if __MOBILE__ Renderer.NativeView.BringSubviewToFront(nativeControl); +#endif nativeControl.Layer.ZPosition = z * 1000; } } diff --git a/Xamarin.Forms.Platform.iOS/VisualElementRenderer.cs b/Xamarin.Forms.Platform.iOS/VisualElementRenderer.cs index 155f8b60..0e7af2a5 100644 --- a/Xamarin.Forms.Platform.iOS/VisualElementRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/VisualElementRenderer.cs @@ -1,13 +1,25 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using UIKit; -using Xamarin.Forms.PlatformConfiguration.iOSSpecific; using RectangleF = CoreGraphics.CGRect; using SizeF = CoreGraphics.CGSize; +#if __MOBILE__ +using Xamarin.Forms.PlatformConfiguration.iOSSpecific; +using UIKit; +using NativeView = UIKit.UIView; +using NativeViewController = UIKit.UIViewController; +using NativeColor = UIKit.UIColor; namespace Xamarin.Forms.Platform.iOS +#else +using AppKit; +using NativeView = AppKit.NSView; +using NativeViewController = AppKit.NSViewController; +using NativeColor = AppKit.NSColor; + +namespace Xamarin.Forms.Platform.MacOS +#endif { [Flags] public enum VisualElementRendererFlags @@ -17,9 +29,9 @@ namespace Xamarin.Forms.Platform.iOS AutoPackage = 1 << 2 } - public class VisualElementRenderer<TElement> : UIView, IVisualElementRenderer, IEffectControlProvider where TElement : VisualElement + public class VisualElementRenderer<TElement> : NativeView, IVisualElementRenderer, IEffectControlProvider where TElement : VisualElement { - readonly UIColor _defaultColor = UIColor.Clear; + readonly NativeColor _defaultColor = NativeColor.Clear; readonly List<EventHandler<VisualElementChangedEventArgs>> _elementChangedHandlers = new List<EventHandler<VisualElementChangedEventArgs>>(); @@ -31,21 +43,30 @@ namespace Xamarin.Forms.Platform.iOS VisualElementPackager _packager; VisualElementTracker _tracker; +#if __MOBILE__ UIVisualEffectView _blur; BlurEffectStyle _previousBlur; +#endif protected VisualElementRenderer() : base(RectangleF.Empty) { _propertyChangedHandler = OnElementPropertyChanged; - BackgroundColor = UIColor.Clear; +#if __MOBILE__ + BackgroundColor = _defaultColor; +#else + WantsLayer = true; + Layer.BackgroundColor = _defaultColor.CGColor; +#endif } +#if __MOBILE__ // prevent possible crashes in overrides - public sealed override UIColor BackgroundColor + public sealed override NativeColor BackgroundColor { get { return base.BackgroundColor; } set { base.BackgroundColor = value; } } +#endif public TElement Element { get; private set; } @@ -73,7 +94,7 @@ namespace Xamarin.Forms.Platform.iOS } } - public static void RegisterEffect(Effect effect, UIView container, UIView control = null) + public static void RegisterEffect(Effect effect, NativeView container, NativeView control = null) { var platformEffect = effect as PlatformEffect; if (platformEffect == null) @@ -106,10 +127,7 @@ namespace Xamarin.Forms.Platform.iOS return NativeView.GetSizeRequest(widthConstraint, heightConstraint); } - public UIView NativeView - { - get { return this; } - } + public NativeView NativeView => this; void IVisualElementRenderer.SetElement(VisualElement element) { @@ -118,13 +136,10 @@ namespace Xamarin.Forms.Platform.iOS public void SetElementSize(Size size) { - Layout.LayoutChildIntoBoundingRegion(Element, new Rectangle(Element.X, Element.Y, size.Width, size.Height)); + Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion(Element, new Rectangle(Element.X, Element.Y, size.Width, size.Height)); } - public virtual UIViewController ViewController - { - get { return null; } - } + public virtual NativeViewController ViewController => null; public event EventHandler<ElementChangedEventArgs<TElement>> ElementChanged; @@ -175,6 +190,7 @@ namespace Xamarin.Forms.Platform.iOS SetAutomationId(Element.AutomationId); } +#if __MOBILE__ public override SizeF SizeThatFits(SizeF size) { return new SizeF(0, 0); @@ -190,6 +206,16 @@ namespace Xamarin.Forms.Platform.iOS Superview.Add(_blur); } } +#else + public override void MouseDown(NSEvent theEvent) + { + bool inViewCell = IsOnViewCell(Element); + + if (Element.InputTransparent || inViewCell) + base.MouseDown(theEvent); + } +#endif + protected override void Dispose(bool disposing) { if ((_flags & VisualElementRendererFlags.Disposed) != 0) @@ -227,22 +253,23 @@ namespace Xamarin.Forms.Platform.iOS for (var i = 0; i < _elementChangedHandlers.Count; i++) _elementChangedHandlers[i](this, args); - var changed = ElementChanged; - if (changed != null) - changed(this, e); - + ElementChanged?.Invoke(this, e); +#if __MOBILE__ if (e.NewElement != null) SetBlur((BlurEffectStyle)e.NewElement.GetValue(PlatformConfiguration.iOSSpecific.VisualElement.BlurEffectProperty)); +#endif } protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName) SetBackgroundColor(Element.BackgroundColor); - else if (e.PropertyName == Layout.IsClippedToBoundsProperty.PropertyName) + else if (e.PropertyName == Xamarin.Forms.Layout.IsClippedToBoundsProperty.PropertyName) UpdateClipToBounds(); +#if __MOBILE__ else if (e.PropertyName == PlatformConfiguration.iOSSpecific.VisualElement.BlurEffectProperty.PropertyName) SetBlur((BlurEffectStyle)Element.GetValue(PlatformConfiguration.iOSSpecific.VisualElement.BlurEffectProperty)); +#endif } protected virtual void OnRegisterEffect(PlatformEffect effect) @@ -258,11 +285,20 @@ namespace Xamarin.Forms.Platform.iOS protected virtual void SetBackgroundColor(Color color) { if (color == Color.Default) +#if __MOBILE__ + BackgroundColor = _defaultColor; else BackgroundColor = color.ToUIColor(); + +#else + Layer.BackgroundColor = _defaultColor.CGColor; + else + Layer.BackgroundColor = color.ToCGColor(); +#endif } +#if __MOBILE__ protected virtual void SetBlur(BlurEffectStyle blur) { if (_previousBlur == blur) @@ -300,21 +336,35 @@ namespace Xamarin.Forms.Platform.iOS _blur = new UIVisualEffectView(blurEffect); LayoutSubviews(); } +#endif protected virtual void UpdateNativeWidget() { } - internal virtual void SendVisualElementInitialized(VisualElement element, UIView nativeView) + internal virtual void SendVisualElementInitialized(VisualElement element, NativeView nativeView) { element.SendViewInitialized(nativeView); } void UpdateClipToBounds() { +#if __MOBILE__ var clippableLayout = Element as Layout; if (clippableLayout != null) ClipsToBounds = clippableLayout.IsClippedToBounds; +#endif + } + + static bool IsOnViewCell(Element element) + { + + if (element.Parent == null) + return false; + else if (element.Parent is ViewCell) + return true; + else + return IsOnViewCell(element.Parent); } } }
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.iOS/VisualElementTracker.cs b/Xamarin.Forms.Platform.iOS/VisualElementTracker.cs index 5b41ca84..29840e2d 100644 --- a/Xamarin.Forms.Platform.iOS/VisualElementTracker.cs +++ b/Xamarin.Forms.Platform.iOS/VisualElementTracker.cs @@ -3,8 +3,13 @@ using System.ComponentModel; using System.Drawing; using System.Threading; using CoreAnimation; +#if __MOBILE__ namespace Xamarin.Forms.Platform.iOS +#else + +namespace Xamarin.Forms.Platform.MacOS +#endif { public class VisualElementTracker : IDisposable { @@ -18,7 +23,9 @@ namespace Xamarin.Forms.Platform.iOS // Track these by hand because the calls down into iOS are too expensive bool _isInteractive; Rectangle _lastBounds; - +#if !__MOBILE__ + Rectangle _lastParentBounds; +#endif CALayer _layer; int _updateCount; @@ -107,12 +114,17 @@ namespace Xamarin.Forms.Platform.iOS var shouldInteract = !view.InputTransparent && view.IsEnabled; if (_isInteractive != shouldInteract) { +#if __MOBILE__ uiview.UserInteractionEnabled = shouldInteract; +#endif _isInteractive = shouldInteract; } var boundsChanged = _lastBounds != view.Bounds; - +#if !__MOBILE__ + var viewParent = view.RealParent as VisualElement; + var parentBoundsChanged = _lastParentBounds != (viewParent == null ? Rectangle.Zero : viewParent.Bounds); +#endif var thread = !boundsChanged && !caLayer.Frame.IsEmpty; var anchorX = (float)view.AnchorX; @@ -136,13 +148,17 @@ namespace Xamarin.Forms.Platform.iOS { if (updateTarget != _updateCount) return; - +#if __MOBILE__ var visualElement = view; +#endif var parent = view.RealParent; var shouldRelayoutSublayers = false; if (isVisible && caLayer.Hidden) { +#if !__MOBILE__ + uiview.Hidden = false; +#endif caLayer.Hidden = false; if (!caLayer.Frame.IsEmpty) shouldRelayoutSublayers = true; @@ -150,6 +166,9 @@ namespace Xamarin.Forms.Platform.iOS if (!isVisible && !caLayer.Hidden) { +#if !__MOBILE__ + uiview.Hidden = true; +#endif caLayer.Hidden = true; shouldRelayoutSublayers = true; } @@ -157,11 +176,26 @@ namespace Xamarin.Forms.Platform.iOS // ripe for optimization var transform = CATransform3D.Identity; +#if __MOBILE__ + bool shouldUpdate = (!(visualElement is Page) || visualElement is ContentPage) && width > 0 && height > 0 && parent != null && boundsChanged; +#else + // We don't care if it's a page or not since bounds of the window can change + // TODO: Find why it doesn't work to check if the parentsBounds changed and remove true; + parentBoundsChanged = true; + bool shouldUpdate = width > 0 && height > 0 && parent != null && (boundsChanged || parentBoundsChanged); +#endif // Dont ever attempt to actually change the layout of a Page unless it is a ContentPage // iOS is a really big fan of you not actually modifying the View's of the UIViewControllers - if ((!(visualElement is Page) || visualElement is ContentPage) && width > 0 && height > 0 && parent != null && boundsChanged) + if (shouldUpdate) { +#if __MOBILE__ var target = new RectangleF(x, y, width, height); +#else + var visualParent = parent as VisualElement; + float newY = visualParent == null ? y : Math.Max(0, (float)(visualParent.Height - y - view.Height)); + var target = new RectangleF(x, newY, width, height); +#endif + // must reset transform prior to setting frame... caLayer.Transform = transform; uiview.Frame = target; @@ -170,11 +204,17 @@ namespace Xamarin.Forms.Platform.iOS } else if (width <= 0 || height <= 0) { + //TODO: FInd why it doesn't work +#if __MOBILE__ caLayer.Hidden = true; +#endif return; } - +#if __MOBILE__ caLayer.AnchorPoint = new PointF(anchorX, anchorY); +#else + caLayer.AnchorPoint = new PointF(anchorX - 0.5f, anchorY - 0.5f); +#endif caLayer.Opacity = opacity; const double epsilon = 0.001; @@ -209,6 +249,9 @@ namespace Xamarin.Forms.Platform.iOS update(); _lastBounds = view.Bounds; +#if !__MOBILE__ + _lastParentBounds = viewParent?.Bounds ?? Rectangle.Zero; +#endif } void SetElement(VisualElement oldElement, VisualElement newElement) @@ -239,14 +282,18 @@ namespace Xamarin.Forms.Platform.iOS if (_layer == null) { +#if !__MOBILE__ + Renderer.NativeView.WantsLayer = true; +#endif _layer = Renderer.NativeView.Layer; +#if __MOBILE__ _isInteractive = Renderer.NativeView.UserInteractionEnabled; +#endif } OnUpdateNativeControl(_layer); - if (NativeControlUpdated != null) - NativeControlUpdated(this, EventArgs.Empty); + NativeControlUpdated?.Invoke(this, EventArgs.Empty); } } }
\ No newline at end of file |