From a0e45ab61ad00d009b2dc43b6caa8acad0f90712 Mon Sep 17 00:00:00 2001 From: "Frank A. Krueger" Date: Fri, 9 Mar 2018 12:56:32 -0800 Subject: [PATCH] Add netstandard1.0 (PCL) support --- Ooui/EventTarget.cs | 5 +- Ooui/Node.cs | 35 ++++++- Ooui/Ooui.csproj | 8 +- Ooui/Platform.cs | 231 +++++++++++++++++++++++--------------------- Ooui/Style.cs | 20 ++++ Ooui/UI.cs | 19 ++-- 6 files changed, 195 insertions(+), 123 deletions(-) diff --git a/Ooui/EventTarget.cs b/Ooui/EventTarget.cs index a37b69a..f13a255 100644 --- a/Ooui/EventTarget.cs +++ b/Ooui/EventTarget.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; namespace Ooui { @@ -21,7 +22,7 @@ namespace Ooui public IReadOnlyList StateMessages { get { lock (stateMessages) { - return new List (stateMessages).AsReadOnly (); + return new ReadOnlyList (stateMessages); } } } @@ -242,7 +243,7 @@ namespace Ooui public override bool CanConvert (Type objectType) { - return typeof (EventTarget).IsAssignableFrom (objectType); + return typeof (EventTarget).GetTypeInfo ().IsAssignableFrom (objectType.GetTypeInfo ()); } } diff --git a/Ooui/Node.cs b/Ooui/Node.cs index 374c016..efea672 100644 --- a/Ooui/Node.cs +++ b/Ooui/Node.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; @@ -11,7 +12,7 @@ namespace Ooui public IReadOnlyList Children { get { lock (children) { - return new List (children).AsReadOnly (); + return new ReadOnlyList (children); } } } @@ -35,7 +36,7 @@ namespace Ooui protected Node (string tagName) : base (tagName) - { + { } public override EventTarget GetElementById (string id) @@ -84,7 +85,7 @@ namespace Ooui return null; lock (children) { if (!children.Remove (child)) { - throw new ArgumentException ("Child not contained in this element", nameof(child)); + throw new ArgumentException ("Child not contained in this element", nameof (child)); } } child.MessageSent -= HandleChildMessageSent; @@ -130,8 +131,8 @@ namespace Ooui case MessageType.Call when message.Key == "removeChild" && message.Value is Array ma && ma.Length == 1: UpdateStateMessages (state => { var mchild = ma.GetValue (0); - Node nextChild = null; - for (var i = 0; i < state.Count; ) { + Node nextChild = null; + for (var i = 0; i < state.Count;) { var x = state[i]; if (x.Key == "insertBefore" && x.Value is Array xa && xa.Length == 2 && ReferenceEquals (xa.GetValue (0), mchild)) { // Remove any inserts for this node @@ -200,4 +201,28 @@ namespace Ooui public abstract void WriteOuterHtml (System.Xml.XmlWriter w); } + + class ReadOnlyList : IReadOnlyList + { + readonly List list; + + public ReadOnlyList (List items) + { + list = new List (items); + } + + T IReadOnlyList.this[int index] => list[index]; + + int IReadOnlyCollection.Count => list.Count; + + IEnumerator IEnumerable.GetEnumerator () + { + return ((IEnumerable)list).GetEnumerator (); + } + + IEnumerator IEnumerable.GetEnumerator () + { + return ((IEnumerable)list).GetEnumerator (); + } + } } diff --git a/Ooui/Ooui.csproj b/Ooui/Ooui.csproj index 98357fe..5dcf5cd 100644 --- a/Ooui/Ooui.csproj +++ b/Ooui/Ooui.csproj @@ -8,12 +8,18 @@ https://github.com/praeclarum/Ooui https://github.com/praeclarum/Ooui/blob/master/LICENSE https://github.com/praeclarum/Ooui.git - netstandard2.0 + netstandard2.0;netstandard1.0 + + + PCL + + + diff --git a/Ooui/Platform.cs b/Ooui/Platform.cs index 287bfa4..cb6c85e 100644 --- a/Ooui/Platform.cs +++ b/Ooui/Platform.cs @@ -7,131 +7,139 @@ namespace Ooui { static class Platform { - static readonly Assembly iosAssembly; - static readonly Type iosUIViewControllerType; - static readonly Type iosUIApplicationType; - static readonly Type iosUIWebViewType; - static readonly Type iosNSUrl; - static readonly Type iosNSUrlRequest; +#if PCL - static readonly Assembly androidAssembly; - static readonly Type androidActivityType; - static readonly Type androidWebViewType; + public static void OpenBrowser (string url, object presenter) + { + } - static Platform () - { - var asms = AppDomain.CurrentDomain.GetAssemblies ().ToDictionary ( - x => x.GetName ().Name); +#else - asms.TryGetValue ("Xamarin.iOS", out iosAssembly); - if (iosAssembly != null) { - iosUIViewControllerType = iosAssembly.GetType ("UIKit.UIViewController"); - iosUIApplicationType = iosAssembly.GetType ("UIKit.UIApplication"); - iosUIWebViewType = iosAssembly.GetType ("UIKit.UIWebView"); - iosNSUrl = iosAssembly.GetType ("Foundation.NSUrl"); - iosNSUrlRequest = iosAssembly.GetType ("Foundation.NSUrlRequest"); - } + static readonly Assembly iosAssembly; + static readonly Type iosUIViewControllerType; + static readonly Type iosUIApplicationType; + static readonly Type iosUIWebViewType; + static readonly Type iosNSUrl; + static readonly Type iosNSUrlRequest; - asms.TryGetValue ("Mono.Android", out androidAssembly); - if (androidAssembly != null) { - androidActivityType = androidAssembly.GetType ("Android.App.Activity"); - androidWebViewType = androidAssembly.GetType ("Android.Webkit.WebView"); - } - } + static readonly Assembly androidAssembly; + static readonly Type androidActivityType; + static readonly Type androidWebViewType; - public static void OpenBrowser (string url, object presenter) - { - if (iosAssembly != null) { - OpenBrowserOniOS (url, presenter); - } - else if (androidAssembly != null) { - OpenBrowserOnAndroid (url, presenter); - } - else { - StartBrowserProcess (url); - } - } + static Platform () + { + var asms = AppDomain.CurrentDomain.GetAssemblies ().ToDictionary ( + x => x.GetName ().Name); - static void OpenBrowserOnAndroid (string url, object presenter) - { - var presenterType = GetObjectType (presenter); + asms.TryGetValue ("Xamarin.iOS", out iosAssembly); + if (iosAssembly != null) { + iosUIViewControllerType = iosAssembly.GetType ("UIKit.UIViewController"); + iosUIApplicationType = iosAssembly.GetType ("UIKit.UIApplication"); + iosUIWebViewType = iosAssembly.GetType ("UIKit.UIWebView"); + iosNSUrl = iosAssembly.GetType ("Foundation.NSUrl"); + iosNSUrlRequest = iosAssembly.GetType ("Foundation.NSUrlRequest"); + } - object presenterWebView = null; - if (presenter != null && androidWebViewType.IsAssignableFrom (presenterType)) { - presenterWebView = presenter; - } + asms.TryGetValue ("Mono.Android", out androidAssembly); + if (androidAssembly != null) { + androidActivityType = androidAssembly.GetType ("Android.App.Activity"); + androidWebViewType = androidAssembly.GetType ("Android.Webkit.WebView"); + } + } - if (presenterWebView == null) { - throw new ArgumentException ("Presenter must be a WebView", nameof(presenter)); - } + public static void OpenBrowser (string url, object presenter) + { + if (iosAssembly != null) { + OpenBrowserOniOS (url, presenter); + } + else if (androidAssembly != null) { + OpenBrowserOnAndroid (url, presenter); + } + else { + StartBrowserProcess (url); + } + } - var m = androidWebViewType.GetMethod ("LoadUrl", BindingFlags.Public|BindingFlags.Instance, null, CallingConventions.Any, new Type[] { typeof(string) }, null); - m.Invoke (presenterWebView, new object[] { url }); - } + static void OpenBrowserOnAndroid (string url, object presenter) + { + var presenterType = GetObjectType (presenter); - static void OpenBrowserOniOS (string url, object presenter) - { - var presenterType = GetObjectType (presenter); + object presenterWebView = null; + if (presenter != null && androidWebViewType.IsAssignableFrom (presenterType)) { + presenterWebView = presenter; + } - // - // Find a presenter view controller - // 1. Try the given presenter - // 2. Find the key window vc - // 3. Create a window? - // - object presenterViewController = null; - if (presenter != null && iosUIViewControllerType.IsAssignableFrom (presenterType)) { - presenterViewController = presenter; - } + if (presenterWebView == null) { + throw new ArgumentException ("Presenter must be a WebView", nameof (presenter)); + } - if (presenterViewController == null) { - var app = iosUIApplicationType.GetProperty ("SharedApplication").GetValue (null, null); - var window = iosUIApplicationType.GetProperty ("KeyWindow").GetValue (app, null); - if (window != null) { - var rvc = window.GetType ().GetProperty ("RootViewController").GetValue (window, null); - if (rvc != null) { - var pvc = rvc.GetType ().GetProperty ("PresentedViewController").GetValue (rvc, null); - presenterViewController = pvc ?? rvc; - } - } - } + var m = androidWebViewType.GetMethod ("LoadUrl", BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, new Type[] { typeof (string) }, null); + m.Invoke (presenterWebView, new object[] { url }); + } - if (presenterViewController == null) { - throw new InvalidOperationException ("Cannot find a view controller from which to present"); - } + static void OpenBrowserOniOS (string url, object presenter) + { + var presenterType = GetObjectType (presenter); - // - // Create the browser - // - var browserVC = Activator.CreateInstance (iosUIViewControllerType); - var browserV = Activator.CreateInstance (iosUIWebViewType); + // + // Find a presenter view controller + // 1. Try the given presenter + // 2. Find the key window vc + // 3. Create a window? + // + object presenterViewController = null; + if (presenter != null && iosUIViewControllerType.IsAssignableFrom (presenterType)) { + presenterViewController = presenter; + } - var nsUrl = iosNSUrl.GetMethod ("FromString").Invoke (null, new object[] { url }); - var nsUrlRequest = iosNSUrlRequest.GetMethod ("FromUrl").Invoke (null, new object[] { nsUrl }); - iosUIWebViewType.GetMethod ("LoadRequest").Invoke (browserV, new object[] { nsUrlRequest }); - iosUIViewControllerType.GetProperty ("View").SetValue (browserVC, browserV, null); + if (presenterViewController == null) { + var app = iosUIApplicationType.GetProperty ("SharedApplication").GetValue (null, null); + var window = iosUIApplicationType.GetProperty ("KeyWindow").GetValue (app, null); + if (window != null) { + var rvc = window.GetType ().GetProperty ("RootViewController").GetValue (window, null); + if (rvc != null) { + var pvc = rvc.GetType ().GetProperty ("PresentedViewController").GetValue (rvc, null); + presenterViewController = pvc ?? rvc; + } + } + } - var m = iosUIViewControllerType.GetMethod ("PresentViewController"); + if (presenterViewController == null) { + throw new InvalidOperationException ("Cannot find a view controller from which to present"); + } - // Console.WriteLine (presenterViewController); - // Console.WriteLine (browserVC); - m.Invoke (presenterViewController, new object[] { browserVC, false, null }); - } + // + // Create the browser + // + var browserVC = Activator.CreateInstance (iosUIViewControllerType); + var browserV = Activator.CreateInstance (iosUIWebViewType); - static Type GetObjectType (object o) - { - var t = typeof (object); - if (o is IReflectableType rt) { - t = rt.GetTypeInfo ().AsType (); - } - else if (o != null) { - t = o.GetType (); - } - return t; - } + var nsUrl = iosNSUrl.GetMethod ("FromString").Invoke (null, new object[] { url }); + var nsUrlRequest = iosNSUrlRequest.GetMethod ("FromUrl").Invoke (null, new object[] { nsUrl }); + iosUIWebViewType.GetMethod ("LoadRequest").Invoke (browserV, new object[] { nsUrlRequest }); + iosUIViewControllerType.GetProperty ("View").SetValue (browserVC, browserV, null); - static Process StartBrowserProcess (string url) - { + var m = iosUIViewControllerType.GetMethod ("PresentViewController"); + + // Console.WriteLine (presenterViewController); + // Console.WriteLine (browserVC); + m.Invoke (presenterViewController, new object[] { browserVC, false, null }); + } + + static Type GetObjectType (object o) + { + var t = typeof (object); + if (o is IReflectableType rt) { + t = rt.GetTypeInfo ().AsType (); + } + else if (o != null) { + t = o.GetType (); + } + return t; + } + + static void StartBrowserProcess (string url) + { // var vs = Environment.GetEnvironmentVariables (); // foreach (System.Collections.DictionaryEntry kv in vs) { // System.Console.WriteLine($"K={kv.Key}, V={kv.Value}"); @@ -139,9 +147,14 @@ namespace Ooui // Console.WriteLine ($"Process.Start {cmd} {args}"); - return Environment.OSVersion.Platform == PlatformID.Unix - ? Process.Start ("open", url) - : Process.Start (new ProcessStartInfo (url) { UseShellExecute = true }); + if (Environment.OSVersion.Platform == PlatformID.Unix) { + Process.Start ("open", url); + } + else { + Process.Start (new ProcessStartInfo (url) { UseShellExecute = true }); + } } + +#endif } } diff --git a/Ooui/Style.cs b/Ooui/Style.cs index 71f3177..c35f499 100644 --- a/Ooui/Style.cs +++ b/Ooui/Style.cs @@ -412,8 +412,19 @@ namespace Ooui return null; if (val is string s) return s; + + if (val is int i) + return i + units; + if (val is double d) + return d.ToString (System.Globalization.CultureInfo.InvariantCulture) + units; + if (val is float f) + return f.ToString (System.Globalization.CultureInfo.InvariantCulture) + units; + +#if !PCL if (val is IConvertible c) return c.ToString (System.Globalization.CultureInfo.InvariantCulture) + units; +#endif + return val.ToString (); } @@ -431,8 +442,17 @@ namespace Ooui return num; } + if (v is int i) + return i; + if (v is double d) + return d; + if (v is float f) + return f; + +#if !PCL if (v is IConvertible c) return c.ToDouble (System.Globalization.CultureInfo.InvariantCulture); +#endif return 0; } diff --git a/Ooui/UI.cs b/Ooui/UI.cs index 5445e51..5d55082 100644 --- a/Ooui/UI.cs +++ b/Ooui/UI.cs @@ -6,12 +6,17 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Net; + +#if !PCL using System.Net.WebSockets; +#endif namespace Ooui { public static class UI { +#if !PCL + static readonly ManualResetEvent started = new ManualResetEvent (false); [ThreadStatic] @@ -22,12 +27,6 @@ namespace Ooui static readonly Dictionary publishedPaths = new Dictionary (); - static readonly Dictionary styles = - new Dictionary (); - static readonly StyleSelectors rules = new StyleSelectors (); - - public static StyleSelectors Styles => rules; - static readonly byte[] clientJsBytes; static readonly string clientJsEtag; @@ -809,6 +808,14 @@ namespace Ooui } } +#endif + + static readonly Dictionary styles = + new Dictionary (); + static readonly StyleSelectors rules = new StyleSelectors (); + + public static StyleSelectors Styles => rules; + public class StyleSelectors { public Style this[string selector] {