From 85b530e36391b25d71c56665a80677b9336e541c Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 24 Nov 2015 22:40:52 +0300 Subject: [PATCH] New ios backend --- Perspex.sln | 61 +++++- .../Perspex.Android/AndroidPlatform.cs | 2 +- src/Perspex.Application/Application.cs | 14 +- src/Perspex.Input/KeyboardDevice.cs | 2 +- src/Perspex.Input/MouseDevice.cs | 2 +- src/iOS/Perspex.iOS/Clipboard.cs | 26 +++ src/iOS/Perspex.iOS/CursorFactory.cs | 11 + src/iOS/Perspex.iOS/Extensions.cs | 15 ++ src/iOS/Perspex.iOS/Perspex.iOS.csproj | 101 +++++++++ src/iOS/Perspex.iOS/PerspexAppDelegate.cs | 50 +++++ src/iOS/Perspex.iOS/PerspexView.cs | 179 ++++++++++++++++ src/iOS/Perspex.iOS/PlatformSettings.cs | 16 ++ .../Perspex.iOS/PlatformThreadingInterface.cs | 56 +++++ .../Perspex.iOS/Properties/AssemblyInfo.cs | 36 ++++ .../Perspex.iOSTestApplication/AppDelegate.cs | 40 ++++ .../Entitlements.plist | 5 + .../GettingStarted.Xamarin | 4 + src/iOS/Perspex.iOSTestApplication/Info.plist | 34 +++ src/iOS/Perspex.iOSTestApplication/Main.cs | 20 ++ .../Perspex.iOSTestApplication.csproj | 197 ++++++++++++++++++ .../Properties/AssemblyInfo.cs | 36 ++++ .../Resources/Default-568h@2x.png | Bin 0 -> 2215 bytes .../packages.config | 6 + 23 files changed, 900 insertions(+), 13 deletions(-) create mode 100644 src/iOS/Perspex.iOS/Clipboard.cs create mode 100644 src/iOS/Perspex.iOS/CursorFactory.cs create mode 100644 src/iOS/Perspex.iOS/Extensions.cs create mode 100644 src/iOS/Perspex.iOS/Perspex.iOS.csproj create mode 100644 src/iOS/Perspex.iOS/PerspexAppDelegate.cs create mode 100644 src/iOS/Perspex.iOS/PerspexView.cs create mode 100644 src/iOS/Perspex.iOS/PlatformSettings.cs create mode 100644 src/iOS/Perspex.iOS/PlatformThreadingInterface.cs create mode 100644 src/iOS/Perspex.iOS/Properties/AssemblyInfo.cs create mode 100644 src/iOS/Perspex.iOSTestApplication/AppDelegate.cs create mode 100644 src/iOS/Perspex.iOSTestApplication/Entitlements.plist create mode 100644 src/iOS/Perspex.iOSTestApplication/GettingStarted.Xamarin create mode 100644 src/iOS/Perspex.iOSTestApplication/Info.plist create mode 100644 src/iOS/Perspex.iOSTestApplication/Main.cs create mode 100644 src/iOS/Perspex.iOSTestApplication/Perspex.iOSTestApplication.csproj create mode 100644 src/iOS/Perspex.iOSTestApplication/Properties/AssemblyInfo.cs create mode 100644 src/iOS/Perspex.iOSTestApplication/Resources/Default-568h@2x.png create mode 100644 src/iOS/Perspex.iOSTestApplication/packages.config diff --git a/Perspex.sln b/Perspex.sln index 1ddd288c70..24c017c309 100644 --- a/Perspex.sln +++ b/Perspex.sln @@ -130,25 +130,32 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Android", "src\Andr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.AndroidTestApplication", "src\Android\Perspex.AndroidTestApplication\Perspex.AndroidTestApplication.csproj", "{FF69B927-C545-49AE-8E16-3D14D621AA12}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iOS", "iOS", "{0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.iOS", "src\iOS\Perspex.iOS\Perspex.iOS.csproj", "{4488AD85-1495-4809-9AA4-DDFE0A48527E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.iOSTestApplication", "src\iOS\Perspex.iOSTestApplication\Perspex.iOSTestApplication.csproj", "{8C923867-8A8F-4F6B-8B80-47D9E8436166}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Shared\RenderHelpers\RenderHelpers.projitems*{fb05ac90-89ba-4f2f-a924-f37875fb547c}*SharedItemsImports = 4 + src\Shared\PlatformSupport\PlatformSupport.projitems*{4488ad85-1495-4809-9aa4-ddfe0a48527e}*SharedItemsImports = 4 src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*SharedItemsImports = 4 src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13 src\Skia\Perspex.Skia\Perspex.Skia.projitems*{2f59f3d0-748d-4652-b01e-e0d954756308}*SharedItemsImports = 13 src\Shared\PlatformSupport\PlatformSupport.projitems*{db070a10-bf39-4752-8456-86e9d5928478}*SharedItemsImports = 4 - src\Skia\Perspex.Skia\Perspex.Skia.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4 src\Shared\RenderHelpers\RenderHelpers.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4 + src\Skia\Perspex.Skia\Perspex.Skia.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4 samples\TestApplicationShared\TestApplicationShared.projitems*{78345174-5b52-4a14-b9fd-d5f2428137f0}*SharedItemsImports = 13 src\Shared\PlatformSupport\PlatformSupport.projitems*{54f237d5-a70a-4752-9656-0c70b1a7b047}*SharedItemsImports = 4 - samples\TestApplicationShared\TestApplicationShared.projitems*{ff69b927-c545-49ae-8e16-3d14d621aa12}*SharedItemsImports = 4 src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13 src\Shared\PlatformSupport\PlatformSupport.projitems*{811a76cf-1cf6-440f-963b-bbe31bd72a82}*SharedItemsImports = 4 - src\Skia\Perspex.Skia\Perspex.Skia.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4 src\Shared\RenderHelpers\RenderHelpers.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4 + src\Skia\Perspex.Skia\Perspex.Skia.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4 + samples\TestApplicationShared\TestApplicationShared.projitems*{8c923867-8a8f-4f6b-8b80-47d9e8436166}*SharedItemsImports = 4 samples\TestApplicationShared\TestApplicationShared.projitems*{e3a1060b-50d0-44e8-88b6-f44ef2e5bd72}*SharedItemsImports = 4 - src\Skia\Perspex.Skia\Perspex.Skia.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4 src\Shared\RenderHelpers\RenderHelpers.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4 + src\Skia\Perspex.Skia\Perspex.Skia.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4 src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1189,6 +1196,50 @@ Global {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|Any CPU.Deploy.0 = Release|Any CPU {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|iPhone.ActiveCfg = Release|Any CPU {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.AppStore|Any CPU.Build.0 = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.AppStore|iPhone.Build.0 = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Debug|iPhone.Build.0 = Debug|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Release|Any CPU.Build.0 = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Release|iPhone.ActiveCfg = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Release|iPhone.Build.0 = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4488AD85-1495-4809-9AA4-DDFE0A48527E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.AppStore|iPhone.ActiveCfg = AppStore|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.AppStore|iPhone.Build.0 = AppStore|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Debug|Any CPU.ActiveCfg = Debug|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Debug|iPhone.ActiveCfg = Debug|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Debug|iPhone.Build.0 = Debug|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Release|Any CPU.ActiveCfg = Release|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Release|iPhone.ActiveCfg = Release|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Release|iPhone.Build.0 = Release|iPhone + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {8C923867-8A8F-4F6B-8B80-47D9E8436166}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1229,5 +1280,7 @@ Global {78345174-5B52-4A14-B9FD-D5F2428137F0} = {9B9E3891-2366-4253-A952-D08BCEB71098} {7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F} {FF69B927-C545-49AE-8E16-3D14D621AA12} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F} + {4488AD85-1495-4809-9AA4-DDFE0A48527E} = {0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1} + {8C923867-8A8F-4F6B-8B80-47D9E8436166} = {0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1} EndGlobalSection EndGlobal diff --git a/src/Android/Perspex.Android/AndroidPlatform.cs b/src/Android/Perspex.Android/AndroidPlatform.cs index 8196571102..b3f4bdaa32 100644 --- a/src/Android/Perspex.Android/AndroidPlatform.cs +++ b/src/Android/Perspex.Android/AndroidPlatform.cs @@ -36,7 +36,7 @@ namespace Perspex.Android .Bind().ToTransient(); SkiaPlatform.Initialize(); - Application.SuppressPlatformInitialization(); + Application.RegisterPlatformCallback(() => { }); PerspexLocator.CurrentMutable.Bind().ToSingleton(); _scalingFactor = global::Android.App.Application.Context.Resources.DisplayMetrics.ScaledDensity; diff --git a/src/Perspex.Application/Application.cs b/src/Perspex.Application/Application.cs index d718d76e71..027ca0b759 100644 --- a/src/Perspex.Application/Application.cs +++ b/src/Perspex.Application/Application.cs @@ -34,7 +34,7 @@ namespace Perspex /// public class Application : IGlobalDataTemplates, IGlobalStyles { - static bool _suppressPlatformInitialization; + static Action _platformInitializationCallback; /// /// The application-global data templates. @@ -62,9 +62,9 @@ namespace Perspex Current = this; } - public static void SuppressPlatformInitialization() + public static void RegisterPlatformCallback(Action cb) { - _suppressPlatformInitialization = true; + _platformInitializationCallback = cb; } /// @@ -185,9 +185,11 @@ namespace Perspex /// The value of Environment.OSVersion.Platform. protected void InitializeSubsystems(int platformID) { - if(_suppressPlatformInitialization) - return; - if (platformID == 4 || platformID == 6) + if (_platformInitializationCallback != null) + { + _platformInitializationCallback(); + } + else if (platformID == 4 || platformID == 6) { InitializeSubsystem("Perspex.Cairo"); InitializeSubsystem("Perspex.Gtk"); diff --git a/src/Perspex.Input/KeyboardDevice.cs b/src/Perspex.Input/KeyboardDevice.cs index 3032a663bd..fc3edad4df 100644 --- a/src/Perspex.Input/KeyboardDevice.cs +++ b/src/Perspex.Input/KeyboardDevice.cs @@ -11,7 +11,7 @@ using Perspex.Interactivity; namespace Perspex.Input { - public abstract class KeyboardDevice : IKeyboardDevice, INotifyPropertyChanged + public class KeyboardDevice : IKeyboardDevice, INotifyPropertyChanged { private IInputElement _focusedElement; diff --git a/src/Perspex.Input/MouseDevice.cs b/src/Perspex.Input/MouseDevice.cs index e3da2caf9b..268b638def 100644 --- a/src/Perspex.Input/MouseDevice.cs +++ b/src/Perspex.Input/MouseDevice.cs @@ -12,7 +12,7 @@ using Perspex.VisualTree; namespace Perspex.Input { - public abstract class MouseDevice : IMouseDevice + public class MouseDevice : IMouseDevice { private int _clickCount; diff --git a/src/iOS/Perspex.iOS/Clipboard.cs b/src/iOS/Perspex.iOS/Clipboard.cs new file mode 100644 index 0000000000..f0a33136f9 --- /dev/null +++ b/src/iOS/Perspex.iOS/Clipboard.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Perspex.Input.Platform; +using UIKit; + +namespace Perspex.iOS +{ + public class Clipboard : IClipboard + { + public Task GetTextAsync() + { + return Task.FromResult(UIPasteboard.General.String); + } + + public Task SetTextAsync(string text) + { + UIPasteboard.General.String = text; + return Task.FromResult(0); + } + + public Task ClearAsync() + { + UIPasteboard.General.String = ""; + return Task.FromResult(0); + } + } +} \ No newline at end of file diff --git a/src/iOS/Perspex.iOS/CursorFactory.cs b/src/iOS/Perspex.iOS/CursorFactory.cs new file mode 100644 index 0000000000..415f4c79b9 --- /dev/null +++ b/src/iOS/Perspex.iOS/CursorFactory.cs @@ -0,0 +1,11 @@ +using System; +using Perspex.Input; +using Perspex.Platform; + +namespace Perspex.iOS +{ + class CursorFactory : IStandardCursorFactory + { + public IPlatformHandle GetCursor(StandardCursorType cursorType) => new PlatformHandle(IntPtr.Zero, "NULL"); + } +} \ No newline at end of file diff --git a/src/iOS/Perspex.iOS/Extensions.cs b/src/iOS/Perspex.iOS/Extensions.cs new file mode 100644 index 0000000000..8bf4ebeb29 --- /dev/null +++ b/src/iOS/Perspex.iOS/Extensions.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using CoreGraphics; + +namespace Perspex.iOS +{ + static class Extensions + { + + public static Size ToPerspex(this CGSize size) => new Size(size.Width, size.Height); + + public static Point ToPerspex(this CGPoint point) => new Point(point.X, point.Y); + } +} diff --git a/src/iOS/Perspex.iOS/Perspex.iOS.csproj b/src/iOS/Perspex.iOS/Perspex.iOS.csproj new file mode 100644 index 0000000000..1a5866908b --- /dev/null +++ b/src/iOS/Perspex.iOS/Perspex.iOS.csproj @@ -0,0 +1,101 @@ + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {4488AD85-1495-4809-9AA4-DDFE0A48527E} + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Perspex.iOS + Resources + Perspex.iOS + + + true + full + false + bin\iPhone\Debug + DEBUG + prompt + 4 + false + true + iPhone Developer + + + none + true + bin\iPhone\Release + prompt + 4 + false + iPhone Developer + + + + + + + + + + + + + + {d211e587-d8bc-45b9-95a4-f297c8fa5200} + Perspex.Animation + + + {799a7bb5-3c2c-48b6-85a7-406a12c420da} + Perspex.Application + + + {b09b78d8-9b26-48b0-9149-d64a2f120f3f} + Perspex.Base + + + {d2221c82-4a25-4583-9b43-d791e3f6820c} + Perspex.Controls + + + {62024b2d-53eb-4638-b26b-85eeaa54866e} + Perspex.Input + + + {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b} + Perspex.Interactivity + + + {42472427-4774-4c81-8aff-9f27b8e31721} + Perspex.Layout + + + {eb582467-6abb-43a1-b052-e981ba910e3a} + Perspex.SceneGraph + + + {f1baa01a-f176-4c6a-b39d-5b40bb1b148f} + Perspex.Styling + + + {47be08a7-5985-410b-9ffc-2264b8ea595f} + Perspex.Skia.iOS + false + false + + + + + + ..\..\..\packages\Rx-Core.2.2.5\lib\portable-windows8+net45+wp8\System.Reactive.Core.dll + + + + + + + + \ No newline at end of file diff --git a/src/iOS/Perspex.iOS/PerspexAppDelegate.cs b/src/iOS/Perspex.iOS/PerspexAppDelegate.cs new file mode 100644 index 0000000000..180d58a34e --- /dev/null +++ b/src/iOS/Perspex.iOS/PerspexAppDelegate.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Perspex.Controls.Platform; +using Perspex.Input; +using Perspex.Input.Platform; +using Perspex.Platform; +using Perspex.Shared.PlatformSupport; +using Perspex.Skia; +using UIKit; + +namespace Perspex.iOS +{ + public class PerspexAppDelegate : UIApplicationDelegate + { + static bool _initialized = false; + internal static MouseDevice MouseDevice; + internal static KeyboardDevice KeyboardDevice; + + protected void InitPerspex(Type appType) + { + if(_initialized) + return; + _initialized = true; + + var window = new UIWindow(UIScreen.MainScreen.Bounds); + var controller = new PerspexViewController(window); + window.RootViewController = controller; + window.MakeKeyAndVisible(); + + Application.RegisterPlatformCallback(() => + { + MouseDevice = new MouseDevice(); + KeyboardDevice = new KeyboardDevice(); + SharedPlatform.Register(appType.Assembly); + PerspexLocator.CurrentMutable + .Bind().ToTransient() + //.Bind().ToTransient() + .Bind().ToTransient() + .Bind().ToConstant(KeyboardDevice) + .Bind().ToConstant(MouseDevice) + .Bind().ToSingleton() + .Bind().ToConstant(new PlatformThreadingInterface()) + .Bind().ToConstant(controller.PerspexView); + SkiaPlatform.Initialize(); + }); + } + } +} diff --git a/src/iOS/Perspex.iOS/PerspexView.cs b/src/iOS/Perspex.iOS/PerspexView.cs new file mode 100644 index 0000000000..be70fefd13 --- /dev/null +++ b/src/iOS/Perspex.iOS/PerspexView.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reactive.Disposables; +using System.Text; +using CoreAnimation; +using CoreGraphics; +using Foundation; +using Perspex.Controls.Platform; +using Perspex.Input; +using Perspex.Input.Raw; +using Perspex.Media; +using Perspex.Platform; +using Perspex.Skia.iOS; +using UIKit; + +namespace Perspex.iOS +{ + class PerspexView : SkiaView, IWindowImpl + { + private readonly UIWindow _window; + private readonly UIViewController _controller; + private IInputRoot _inputRoot; + + public PerspexView(UIWindow window, UIViewController controller) + { + if (controller == null) throw new ArgumentNullException(nameof(controller)); + _window = window; + _controller = controller; + AutoresizingMask = UIViewAutoresizing.All; + AutoFit(); + UIApplication.Notifications.ObserveDidChangeStatusBarOrientation(delegate { AutoFit(); }); + UIApplication.Notifications.ObserveDidChangeStatusBarFrame(delegate { AutoFit(); }); + } + + + void AutoFit() + { + var needFlip = !UIDevice.CurrentDevice.CheckSystemVersion(8, 0) && + (_controller.InterfaceOrientation == UIInterfaceOrientation.LandscapeLeft + || _controller.InterfaceOrientation == UIInterfaceOrientation.LandscapeRight); + + var frame = UIScreen.MainScreen.Bounds; + if (needFlip) + Frame = new CGRect(frame.Y, frame.X, frame.Height, frame.Width); + else + Frame = frame; + } + + public Action Activated { get; set; } + public Action Closed { get; set; } + public Action Deactivated { get; set; } + public Action Input { get; set; } + public Action Paint { get; set; } + public Action Resized { get; set; } + + + public IPlatformHandle Handle => PerspexPlatformHandle; + + + public override void LayoutSubviews() => Resized?.Invoke(ClientSize); + + public Size ClientSize + { + get { return Bounds.Size.ToPerspex(); } + set { Resized?.Invoke(ClientSize); } + } + + public void Activate() + { + } + + protected override void Draw() + { + Paint?.Invoke(new Rect(new Point(), ClientSize)); + } + + public void Invalidate(Rect rect) => DrawOnNextFrame(); + + public void SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot; + + public Point PointToScreen(Point point) => point; + + public void SetCursor(IPlatformHandle cursor) + { + //Not supported + } + + public void Show() + { + } + + public Size MaxClientSize => Bounds.Size.ToPerspex(); + public void SetTitle(string title) + { + //Not supported + } + + public IDisposable ShowDialog() + { + //Not supported + return Disposable.Empty; + } + + public void Hide() + { + //Not supported + } + + public override void TouchesEnded(NSSet touches, UIEvent evt) + { + var touch = touches.AnyObject as UITouch; + if (touch != null) + { + var location = touch.LocationInView(this).ToPerspex(); + + Input?.Invoke(new RawMouseEventArgs( + PerspexAppDelegate.MouseDevice, + (uint) touch.Timestamp, + _inputRoot, + RawMouseEventType.LeftButtonUp, + location, + InputModifiers.None)); + } + } + + Point _touchLastPoint; + public override void TouchesBegan(NSSet touches, UIEvent evt) + { + var touch = touches.AnyObject as UITouch; + if (touch != null) + { + var location = touch.LocationInView(this).ToPerspex(); + _touchLastPoint = location; + Input?.Invoke(new RawMouseEventArgs(PerspexAppDelegate.MouseDevice, (uint) touch.Timestamp, _inputRoot, + RawMouseEventType.Move, location, InputModifiers.None)); + + Input?.Invoke(new RawMouseEventArgs(PerspexAppDelegate.MouseDevice, (uint) touch.Timestamp, _inputRoot, + RawMouseEventType.LeftButtonDown, location, InputModifiers.None)); + } + } + + public override void TouchesMoved(NSSet touches, UIEvent evt) + { + var touch = touches.AnyObject as UITouch; + if (touch != null) + { + var location = touch.LocationInView(this).ToPerspex(); + if (PerspexAppDelegate.MouseDevice.Captured != null) + Input?.Invoke(new RawMouseEventArgs(PerspexAppDelegate.MouseDevice, (uint) touch.Timestamp, _inputRoot, + RawMouseEventType.Move, location, InputModifiers.LeftMouseButton)); + else + { + Input?.Invoke(new RawMouseWheelEventArgs(PerspexAppDelegate.MouseDevice, (uint) touch.Timestamp, + _inputRoot, location, location - _touchLastPoint, InputModifiers.LeftMouseButton)); + } + _touchLastPoint = location; + } + } + + + } + + class PerspexViewController : UIViewController + { + public PerspexView PerspexView { get; } + + public PerspexViewController(UIWindow window) + { + PerspexView = new PerspexView(window, this); + } + + public override void LoadView() + { + View = PerspexView; + } + } +} diff --git a/src/iOS/Perspex.iOS/PlatformSettings.cs b/src/iOS/Perspex.iOS/PlatformSettings.cs new file mode 100644 index 0000000000..87b073bbe9 --- /dev/null +++ b/src/iOS/Perspex.iOS/PlatformSettings.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Perspex.Platform; +using UIKit; + +namespace Perspex.iOS +{ + class PlatformSettings : IPlatformSettings + { + public Size DoubleClickSize =>new Size(4, 4); + public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(200); + public double RenderScalingFactor => UIScreen.MainScreen.Scale; + public double LayoutScalingFactor => 1; + } +} diff --git a/src/iOS/Perspex.iOS/PlatformThreadingInterface.cs b/src/iOS/Perspex.iOS/PlatformThreadingInterface.cs new file mode 100644 index 0000000000..00e2474238 --- /dev/null +++ b/src/iOS/Perspex.iOS/PlatformThreadingInterface.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Disposables; +using System.Text; +using System.Threading; +using CoreAnimation; +using Foundation; +using Perspex.Platform; +using Perspex.Shared.PlatformSupport; + +namespace Perspex.iOS +{ + class PlatformThreadingInterface : IPlatformThreadingInterface + { + readonly List _timers = new List(); + bool _signaled; + + public PlatformThreadingInterface() + { + CADisplayLink.Create(OnFrame).AddToRunLoop(NSRunLoop.Main, NSRunLoop.NSDefaultRunLoopMode); + } + + private void OnFrame() + { + foreach (var timer in _timers.ToList()) + { + timer(); + } + + if (_signaled) + { + _signaled = false; + Signaled?.Invoke(); + } + } + + public void RunLoop(CancellationToken cancellationToken) + { + } + + public IDisposable StartTimer(TimeSpan interval, Action tick) + { + _timers.Add(tick); + return Disposable.Create(() => _timers.Remove(tick)); + } + + public void Signal() + { + _signaled = true; + } + + public bool CurrentThreadIsLoopThread => NSThread.Current.IsMainThread; + public event Action Signaled; + } +} diff --git a/src/iOS/Perspex.iOS/Properties/AssemblyInfo.cs b/src/iOS/Perspex.iOS/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..d8e5078bdd --- /dev/null +++ b/src/iOS/Perspex.iOS/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Perspex.iOS")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Perspex.iOS")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4488ad85-1495-4809-9aa4-ddfe0a48527e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/iOS/Perspex.iOSTestApplication/AppDelegate.cs b/src/iOS/Perspex.iOSTestApplication/AppDelegate.cs new file mode 100644 index 0000000000..9227062b13 --- /dev/null +++ b/src/iOS/Perspex.iOSTestApplication/AppDelegate.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Foundation; +using Perspex.iOS; +using Perspex.Threading; +using TestApplication; +using UIKit; + +namespace Perspex.iOSTestApplication +{ + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to + // application events from iOS. + [Register("AppDelegate")] + public partial class AppDelegate : PerspexAppDelegate + { + // + // This method is invoked when the application has loaded and is ready to run. In this + // method you should instantiate the window, load the UI into it and then make the window + // visible. + // + // You have 17 seconds to return from this method, or iOS will terminate your application. + // + public override bool FinishedLaunching(UIApplication uiapp, NSDictionary options) + { + InitPerspex (typeof (App)); + + var app = new App(); + + MainWindow.RootNamespace = "Perspex.iOSTestApplication"; + var window = MainWindow.Create(); + window.Show(); + app.Run(window); + + return true; + } + } +} \ No newline at end of file diff --git a/src/iOS/Perspex.iOSTestApplication/Entitlements.plist b/src/iOS/Perspex.iOSTestApplication/Entitlements.plist new file mode 100644 index 0000000000..0c67376eba --- /dev/null +++ b/src/iOS/Perspex.iOSTestApplication/Entitlements.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/src/iOS/Perspex.iOSTestApplication/GettingStarted.Xamarin b/src/iOS/Perspex.iOSTestApplication/GettingStarted.Xamarin new file mode 100644 index 0000000000..810f716685 --- /dev/null +++ b/src/iOS/Perspex.iOSTestApplication/GettingStarted.Xamarin @@ -0,0 +1,4 @@ + + GS\iOS\CS\iOSApp\GettingStarted.html + false + \ No newline at end of file diff --git a/src/iOS/Perspex.iOSTestApplication/Info.plist b/src/iOS/Perspex.iOSTestApplication/Info.plist new file mode 100644 index 0000000000..a6654de44c --- /dev/null +++ b/src/iOS/Perspex.iOSTestApplication/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDisplayName + Perspex.iOSTestApplication + CFBundleIdentifier + com.your-company.Perspex.iOSTestApplication + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 7.0 + + \ No newline at end of file diff --git a/src/iOS/Perspex.iOSTestApplication/Main.cs b/src/iOS/Perspex.iOSTestApplication/Main.cs new file mode 100644 index 0000000000..697e57c0d4 --- /dev/null +++ b/src/iOS/Perspex.iOSTestApplication/Main.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using Foundation; +using UIKit; + +namespace Perspex.iOSTestApplication +{ + public class Application + { + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, "AppDelegate"); + } + } +} \ No newline at end of file diff --git a/src/iOS/Perspex.iOSTestApplication/Perspex.iOSTestApplication.csproj b/src/iOS/Perspex.iOSTestApplication/Perspex.iOSTestApplication.csproj new file mode 100644 index 0000000000..42c0c2eccd --- /dev/null +++ b/src/iOS/Perspex.iOSTestApplication/Perspex.iOSTestApplication.csproj @@ -0,0 +1,197 @@ + + + + Debug + iPhoneSimulator + {8C923867-8A8F-4F6B-8B80-47D9E8436166} + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + Perspex.iOSTestApplication + Resources + PerspexiOSTestApplication + + + true + full + false + bin\iPhoneSimulator\Debug + DEBUG + prompt + 4 + false + i386 + None + true + + + none + true + bin\iPhoneSimulator\Release + prompt + 4 + None + i386 + false + + + true + full + false + bin\iPhone\Debug + DEBUG + prompt + 4 + false + ARMv7, ARM64 + Entitlements.plist + iPhone Developer + True + 9.1 + SdkOnly + False + False + False + False + True + True + True + False + + + + none + true + bin\iPhone\Release + prompt + 4 + Entitlements.plist + ARMv7, ARM64 + false + iPhone Developer + + + none + True + bin\iPhone\Ad-Hoc + prompt + 4 + False + ARMv7, ARM64 + Entitlements.plist + True + Automatic:AdHoc + iPhone Distribution + + + none + True + bin\iPhone\AppStore + prompt + 4 + False + ARMv7, ARM64 + Entitlements.plist + Automatic:AppStore + iPhone Distribution + + + + + + + + + + + + + + + + ..\..\..\packages\Rx-Core.2.2.5\lib\portable-windows8+net45+wp8\System.Reactive.Core.dll + True + + + ..\..\..\packages\Rx-Interfaces.2.2.5\lib\portable-windows8+net45+wp8\System.Reactive.Interfaces.dll + True + + + ..\..\..\packages\Rx-Linq.2.2.5\lib\portable-windows8+net45+wp8\System.Reactive.Linq.dll + True + + + + + + + + + + + {3e53a01a-b331-47f3-b828-4a5717e77a24} + Perspex.Markup.Xaml + + + {6417e941-21bc-467b-a771-0de389353ce6} + Perspex.Markup + + + {d211e587-d8bc-45b9-95a4-f297c8fa5200} + Perspex.Animation + + + {799a7bb5-3c2c-48b6-85a7-406a12c420da} + Perspex.Application + + + {b09b78d8-9b26-48b0-9149-d64a2f120f3f} + Perspex.Base + + + {d2221c82-4a25-4583-9b43-d791e3f6820c} + Perspex.Controls + + + {5fb2b005-0a7f-4dad-add4-3ed01444e63d} + Perspex.HtmlRenderer + + + {62024b2d-53eb-4638-b26b-85eeaa54866e} + Perspex.Input + + + {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b} + Perspex.Interactivity + + + {42472427-4774-4c81-8aff-9f27b8e31721} + Perspex.Layout + + + {eb582467-6abb-43a1-b052-e981ba910e3a} + Perspex.SceneGraph + + + {f1baa01a-f176-4c6a-b39d-5b40bb1b148f} + Perspex.Styling + + + {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f} + Perspex.Themes.Default + + + {47be08a7-5985-410b-9ffc-2264b8ea595f} + Perspex.Skia.iOS + false + false + + + {4488ad85-1495-4809-9aa4-ddfe0a48527e} + Perspex.iOS + false + false + + + + + \ No newline at end of file diff --git a/src/iOS/Perspex.iOSTestApplication/Properties/AssemblyInfo.cs b/src/iOS/Perspex.iOSTestApplication/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..2505a45c78 --- /dev/null +++ b/src/iOS/Perspex.iOSTestApplication/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Perspex.iOSTestApplication")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Perspex.iOSTestApplication")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8c923867-8a8f-4f6b-8b80-47d9e8436166")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/iOS/Perspex.iOSTestApplication/Resources/Default-568h@2x.png b/src/iOS/Perspex.iOSTestApplication/Resources/Default-568h@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..29973dcbed50cb67f5f522d4fd9cb5caddda6cc4 GIT binary patch literal 2215 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sU@72W0*ZWnTNDnYI14-?iy0WWg+Z8+Vb&Z8 z1_q8uPZ!6Kid%0F8ZrWv99r$Ma}qo=E%%Q~loCIFNg8Dsze literal 0 HcmV?d00001 diff --git a/src/iOS/Perspex.iOSTestApplication/packages.config b/src/iOS/Perspex.iOSTestApplication/packages.config new file mode 100644 index 0000000000..4488cb8b7d --- /dev/null +++ b/src/iOS/Perspex.iOSTestApplication/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file