Scaffold the Ooui platform

This commit is contained in:
Frank A. Krueger 2017-11-08 23:57:04 -08:00
parent f06b57f240
commit 3d148e7e9f
9 changed files with 302 additions and 10 deletions

View File

@ -4,7 +4,7 @@ using Ooui.Forms.Renderers;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Internals; using Xamarin.Forms.Internals;
[assembly: Dependency (typeof (ResourcesProvider))]
[assembly: ExportRenderer (typeof (Button), typeof (ButtonRenderer))] [assembly: ExportRenderer (typeof (Button), typeof (ButtonRenderer))]
namespace Ooui.Forms namespace Ooui.Forms

View File

@ -0,0 +1,9 @@
using System;
using Xamarin.Forms;
namespace Ooui.Forms
{
public interface IVisualElementRenderer : IRegisterable, IDisposable
{
}
}

View File

@ -1,26 +1,38 @@
using System; using System;
using Xamarin.Forms;
namespace Ooui.Forms namespace Xamarin.Forms
{ {
public static class PageExtensions public static class PageExtensions
{ {
public static void Publish (this Xamarin.Forms.Page page, string path) public static void Publish (this Xamarin.Forms.Page page, string path)
{ {
UI.Publish (path, () => page.CreateElement ()); Ooui.UI.Publish (path, () => page.CreateElement ());
} }
public static void PublishShared (this Xamarin.Forms.Page page, string path) public static void PublishShared (this Xamarin.Forms.Page page, string path)
{ {
var lazyPage = new Lazy<Element> ((() => page.CreateElement ()), true); var lazyPage = new Lazy<Ooui.Element> ((() => page.CreateElement ()), true);
UI.Publish (path, () => lazyPage.Value); Ooui.UI.Publish (path, () => lazyPage.Value);
} }
public static Element CreateElement (this Xamarin.Forms.Page page) public static Ooui.Element CreateElement (this Xamarin.Forms.Page page)
{ {
if (!Xamarin.Forms.Forms.IsInitialized) if (!Xamarin.Forms.Forms.IsInitialized)
throw new InvalidOperationException ("call Forms.Init() before this"); throw new InvalidOperationException ("call Forms.Init() before this");
throw new NotImplementedException (); if (!(page.RealParent is Application)) {
var app = new DefaultApplication ();
app.MainPage = page;
}
var result = new Ooui.Forms.Platform ();
result.SetPage (page);
return result.Element;
}
class DefaultApplication : Application
{
} }
} }
} }

View File

@ -1,13 +1,31 @@
using System; using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Ooui.Forms.Renderers;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Internals; using Xamarin.Forms.Internals;
namespace Ooui.Forms namespace Ooui.Forms
{ {
public class Platform : BindableObject, IPlatform, IDisposable public class Platform : BindableObject, IPlatform, INavigation, IDisposable
{ {
bool _disposed; bool _disposed;
public Element Element { get; private set; }
public Page Page { get; private set; }
IReadOnlyList<Page> INavigation.ModalStack => throw new NotImplementedException ();
IReadOnlyList<Page> INavigation.NavigationStack => throw new NotImplementedException ();
public static readonly BindableProperty RendererProperty = BindableProperty.CreateAttached ("Renderer", typeof (IVisualElementRenderer), typeof (Platform), default (IVisualElementRenderer),
propertyChanged: (bindable, oldvalue, newvalue) => {
var view = bindable as VisualElement;
if (view != null)
view.IsPlatformEnabled = newvalue != null;
});
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
if (_disposed) if (_disposed)
@ -19,9 +37,128 @@ namespace Ooui.Forms
MessagingCenter.Unsubscribe<Page, bool>(this, Page.BusySetSignalName); MessagingCenter.Unsubscribe<Page, bool>(this, Page.BusySetSignalName);
} }
public static IVisualElementRenderer CreateRenderer (VisualElement element)
{
var renderer = Registrar.Registered.GetHandler<IVisualElementRenderer> (element.GetType ()) ?? new DefaultRenderer ();
//renderer.SetElement (element);
return renderer;
}
public static IVisualElementRenderer GetRenderer (VisualElement bindable)
{
return (IVisualElementRenderer)bindable.GetValue (RendererProperty);
}
public static void SetRenderer (VisualElement bindable, IVisualElementRenderer value)
{
bindable.SetValue (RendererProperty, value);
}
protected override void OnBindingContextChanged ()
{
SetInheritedBindingContext (Page, BindingContext);
base.OnBindingContextChanged ();
}
public SizeRequest GetNativeSize(VisualElement view, double widthConstraint, double heightConstraint) public SizeRequest GetNativeSize(VisualElement view, double widthConstraint, double heightConstraint)
{ {
return new SizeRequest(new Size(100, 100)); return new SizeRequest(new Size(100, 100));
} }
public void SetPage (Page newRoot)
{
if (newRoot == null)
return;
if (Page != null)
throw new NotImplementedException ();
Page = newRoot;
Page.Platform = this;
AddChild (Page);
//Page.DescendantRemoved += HandleChildRemoved;
Application.Current.NavigationProxy.Inner = this;
}
void AddChild (VisualElement view)
{
if (!Application.IsApplicationOrNull (view.RealParent))
Console.Error.WriteLine ("Tried to add parented view to canvas directly");
if (GetRenderer (view) == null) {
var viewRenderer = CreateRenderer (view);
SetRenderer (view, viewRenderer);
//_renderer.View.AddSubview (viewRenderer.NativeView);
//if (viewRenderer.ViewController != null)
// _renderer.AddChildViewController (viewRenderer.ViewController);
//viewRenderer.NativeView.Frame = new RectangleF (0, 0, _renderer.View.Bounds.Width, _renderer.View.Bounds.Height);
//viewRenderer.SetElementSize (new Size (_renderer.View.Bounds.Width, _renderer.View.Bounds.Height));
}
else
Console.Error.WriteLine ("Potential view double add");
}
void INavigation.InsertPageBefore (Page page, Page before)
{
throw new NotImplementedException ();
}
Task<Page> INavigation.PopAsync ()
{
throw new NotImplementedException ();
}
Task<Page> INavigation.PopAsync (bool animated)
{
throw new NotImplementedException ();
}
Task<Page> INavigation.PopModalAsync ()
{
throw new NotImplementedException ();
}
Task<Page> INavigation.PopModalAsync (bool animated)
{
throw new NotImplementedException ();
}
Task INavigation.PopToRootAsync ()
{
throw new NotImplementedException ();
}
Task INavigation.PopToRootAsync (bool animated)
{
throw new NotImplementedException ();
}
Task INavigation.PushAsync (Page page)
{
throw new NotImplementedException ();
}
Task INavigation.PushAsync (Page page, bool animated)
{
throw new NotImplementedException ();
}
Task INavigation.PushModalAsync (Page page)
{
throw new NotImplementedException ();
}
Task INavigation.PushModalAsync (Page page, bool animated)
{
throw new NotImplementedException ();
}
void INavigation.RemovePage (Page page)
{
throw new NotImplementedException ();
}
} }
} }

View File

@ -0,0 +1,12 @@
using System;
using Xamarin.Forms;
namespace Ooui.Forms.Renderers
{
public class DefaultRenderer : VisualElementRenderer<VisualElement>
{
public DefaultRenderer () : base ("div")
{
}
}
}

View File

@ -3,7 +3,40 @@ using Xamarin.Forms;
namespace Ooui.Forms.Renderers namespace Ooui.Forms.Renderers
{ {
public class ElementRenderer<TElement, TNativeElement> where TElement : View where TNativeElement : Ooui.Element public class ElementRenderer<TElement, TNativeElement> : IVisualElementRenderer where TElement : View where TNativeElement : Ooui.Element
{ {
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose (bool disposing)
{
if (!disposedValue) {
if (disposing) {
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~ElementRenderer() {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose ()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose (true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
} }
} }

View File

@ -0,0 +1,41 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Xamarin.Forms.Internals;
namespace Ooui.Forms
{
public class ResourcesProvider : ISystemResourcesProvider
{
readonly Res res = new Res ();
public IResourceDictionary GetSystemResources ()
{
return res;
}
class Res : IResourceDictionary
{
readonly ConcurrentDictionary<string, object> values =
new ConcurrentDictionary<string, object> ();
public event EventHandler<ResourcesChangedEventArgs> ValuesChanged;
public bool TryGetValue (string key, out object value)
{
return values.TryGetValue (key, out value);
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator ()
{
return values.GetEnumerator ();
}
IEnumerator IEnumerable.GetEnumerator ()
{
return values.GetEnumerator ();
}
}
}
}

View File

@ -0,0 +1,45 @@
using System;
using Xamarin.Forms;
namespace Ooui.Forms
{
public class VisualElementRenderer<TElement> : Element, IVisualElementRenderer where TElement : VisualElement
{
public VisualElementRenderer (string tagName) : base (tagName)
{
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose (bool disposing)
{
if (!disposedValue) {
if (disposing) {
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~VisualElementRenderer() {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose ()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose (true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
}

View File

@ -402,6 +402,9 @@ namespace Ooui
Element element = null; Element element = null;
try { try {
element = elementHandler.GetElement (); element = elementHandler.GetElement ();
if (element == null)
throw new Exception ("Handler returned a null element");
} }
catch (Exception ex) { catch (Exception ex) {
listenerContext.Response.StatusCode = 500; listenerContext.Response.StatusCode = 500;