Use spaces to match Ooui

This commit is contained in:
Frank A. Krueger 2017-11-09 13:03:56 -08:00
parent e3627b5b90
commit a887133288
14 changed files with 560 additions and 552 deletions

View File

@ -9,12 +9,12 @@ using Xamarin.Forms.Internals;
namespace Ooui.Forms namespace Ooui.Forms
{ {
[AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true)] [AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class ExportRendererAttribute : HandlerAttribute public sealed class ExportRendererAttribute : HandlerAttribute
{ {
public ExportRendererAttribute (Type handler, Type target) public ExportRendererAttribute (Type handler, Type target)
: base (handler, target) : base (handler, target)
{ {
} }
} }
} }

View File

@ -11,101 +11,101 @@ using Ooui;
namespace Xamarin.Forms namespace Xamarin.Forms
{ {
public static class Forms public static class Forms
{ {
public static bool IsInitialized { get; private set; } public static bool IsInitialized { get; private set; }
public static void Init () public static void Init ()
{ {
if (IsInitialized) if (IsInitialized)
return; return;
IsInitialized = true; IsInitialized = true;
Log.Listeners.Add (new DelegateLogListener ((c, m) => Trace.WriteLine (m, c))); Log.Listeners.Add (new DelegateLogListener ((c, m) => Trace.WriteLine (m, c)));
Device.SetIdiom (TargetIdiom.Desktop); Device.SetIdiom (TargetIdiom.Desktop);
Device.PlatformServices = new OouiPlatformServices (); Device.PlatformServices = new OouiPlatformServices ();
Device.Info = new OouiDeviceInfo (); Device.Info = new OouiDeviceInfo ();
Registrar.RegisterAll (new[] { Registrar.RegisterAll (new[] {
typeof(ExportRendererAttribute), typeof(ExportRendererAttribute),
//typeof(ExportCellAttribute), //typeof(ExportCellAttribute),
//typeof(ExportImageSourceHandlerAttribute), //typeof(ExportImageSourceHandlerAttribute),
}); });
} }
public static event EventHandler<ViewInitializedEventArgs> ViewInitialized; public static event EventHandler<ViewInitializedEventArgs> ViewInitialized;
public static void SendViewInitialized (this VisualElement self, Ooui.Element nativeView) public static void SendViewInitialized (this VisualElement self, Ooui.Element nativeView)
{ {
ViewInitialized?.Invoke (self, new ViewInitializedEventArgs { View = self, NativeView = nativeView }); ViewInitialized?.Invoke (self, new ViewInitializedEventArgs { View = self, NativeView = nativeView });
} }
class OouiDeviceInfo : DeviceInfo class OouiDeviceInfo : DeviceInfo
{ {
public override Size PixelScreenSize => new Size (640, 480); public override Size PixelScreenSize => new Size (640, 480);
public override Size ScaledScreenSize => PixelScreenSize; public override Size ScaledScreenSize => PixelScreenSize;
public override double ScalingFactor => 1; public override double ScalingFactor => 1;
} }
class OouiPlatformServices : IPlatformServices class OouiPlatformServices : IPlatformServices
{ {
public bool IsInvokeRequired => false; public bool IsInvokeRequired => false;
public string RuntimePlatform => "Ooui"; public string RuntimePlatform => "Ooui";
public void BeginInvokeOnMainThread (Action action) public void BeginInvokeOnMainThread (Action action)
{ {
Task.Run (action); Task.Run (action);
} }
public Ticker CreateTicker () public Ticker CreateTicker ()
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public Assembly[] GetAssemblies () public Assembly[] GetAssemblies ()
{ {
return AppDomain.CurrentDomain.GetAssemblies (); return AppDomain.CurrentDomain.GetAssemblies ();
} }
public string GetMD5Hash (string input) public string GetMD5Hash (string input)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public double GetNamedSize (NamedSize size, Type targetElementType, bool useOldSizes) public double GetNamedSize (NamedSize size, Type targetElementType, bool useOldSizes)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public Task<Stream> GetStreamAsync (Uri uri, CancellationToken cancellationToken) public Task<Stream> GetStreamAsync (Uri uri, CancellationToken cancellationToken)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public IIsolatedStorageFile GetUserStoreForApplication () public IIsolatedStorageFile GetUserStoreForApplication ()
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public void OpenUriAction (Uri uri) public void OpenUriAction (Uri uri)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public void StartTimer (TimeSpan interval, Func<bool> callback) public void StartTimer (TimeSpan interval, Func<bool> callback)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
} }
public class ViewInitializedEventArgs public class ViewInitializedEventArgs
{ {
public VisualElement View { get; set; } public VisualElement View { get; set; }
public Ooui.Element NativeView { get; set; } public Ooui.Element NativeView { get; set; }
} }
} }
} }

View File

@ -4,6 +4,13 @@
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType></DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Xamarin.Forms" Version="2.4.0.38779" /> <PackageReference Include="Xamarin.Forms" Version="2.4.0.38779" />
</ItemGroup> </ItemGroup>

View File

@ -3,36 +3,36 @@ using Xamarin.Forms;
namespace Xamarin.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)
{ {
Ooui.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<Ooui.Element> ((() => page.CreateElement ()), true); var lazyPage = new Lazy<Ooui.Element> ((() => page.CreateElement ()), true);
Ooui.UI.Publish (path, () => lazyPage.Value); Ooui.UI.Publish (path, () => lazyPage.Value);
} }
public static Ooui.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");
if (!(page.RealParent is Application)) { if (!(page.RealParent is Application)) {
var app = new DefaultApplication (); var app = new DefaultApplication ();
app.MainPage = page; app.MainPage = page;
} }
var result = new Ooui.Forms.Platform (); var result = new Ooui.Forms.Platform ();
result.SetPage (page); result.SetPage (page);
return result.Element; return result.Element;
} }
class DefaultApplication : Application class DefaultApplication : Application
{ {
} }
} }
} }

View File

@ -7,167 +7,167 @@ using Xamarin.Forms.Internals;
namespace Ooui.Forms namespace Ooui.Forms
{ {
public class Platform : BindableObject, IPlatform, INavigation, IDisposable public class Platform : BindableObject, IPlatform, INavigation, IDisposable
{ {
bool _disposed; bool _disposed;
readonly PlatformRenderer _renderer; readonly PlatformRenderer _renderer;
public Ooui.Element Element => _renderer;
public Page Page { get; private set; }
IReadOnlyList<Page> INavigation.ModalStack => throw new NotImplementedException (); public Ooui.Element Element => _renderer;
IReadOnlyList<Page> INavigation.NavigationStack => throw new NotImplementedException (); public Page Page { get; private set; }
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;
});
public Platform ()
{
_renderer = new PlatformRenderer (this);
}
void IDisposable.Dispose() IReadOnlyList<Page> INavigation.ModalStack => throw new NotImplementedException ();
{
if (_disposed)
return;
_disposed = true;
MessagingCenter.Unsubscribe<Page, ActionSheetArguments>(this, Page.ActionSheetSignalName);
MessagingCenter.Unsubscribe<Page, AlertArguments>(this, Page.AlertSignalName);
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) IReadOnlyList<Page> INavigation.NavigationStack => throw new NotImplementedException ();
{
return new SizeRequest(new Size(100, 100));
}
public void SetPage (Page newRoot) public static readonly BindableProperty RendererProperty = BindableProperty.CreateAttached ("Renderer", typeof (IVisualElementRenderer), typeof (Platform), default (IVisualElementRenderer),
{ propertyChanged: (bindable, oldvalue, newvalue) => {
if (newRoot == null) var view = bindable as VisualElement;
return; if (view != null)
if (Page != null) view.IsPlatformEnabled = newvalue != null;
throw new NotImplementedException (); });
Page = newRoot;
Page.Platform = this;
AddChild (Page);
Page.DescendantRemoved += HandleChildRemoved;
Application.Current.NavigationProxy.Inner = this;
}
void HandleChildRemoved (object sender, ElementEventArgs e) public Platform ()
{ {
throw new NotImplementedException (); _renderer = new PlatformRenderer (this);
} }
void AddChild (VisualElement view) void IDisposable.Dispose ()
{ {
if (!Application.IsApplicationOrNull (view.RealParent)) if (_disposed)
Console.Error.WriteLine ("Tried to add parented view to canvas directly"); return;
_disposed = true;
if (GetRenderer (view) == null) {
var viewRenderer = CreateRenderer (view);
SetRenderer (view, viewRenderer);
_renderer.AppendChild (viewRenderer.NativeView);
viewRenderer.SetElementSize (new Size (640, 480));
}
else
Console.Error.WriteLine ("Potential view double add");
}
void INavigation.InsertPageBefore (Page page, Page before) MessagingCenter.Unsubscribe<Page, ActionSheetArguments> (this, Page.ActionSheetSignalName);
{ MessagingCenter.Unsubscribe<Page, AlertArguments> (this, Page.AlertSignalName);
throw new NotImplementedException (); MessagingCenter.Unsubscribe<Page, bool> (this, Page.BusySetSignalName);
} }
Task<Page> INavigation.PopAsync () public static IVisualElementRenderer CreateRenderer (VisualElement element)
{ {
throw new NotImplementedException (); var renderer = Registrar.Registered.GetHandler<IVisualElementRenderer> (element.GetType ()) ?? new DefaultRenderer ();
} renderer.SetElement (element);
return renderer;
}
Task<Page> INavigation.PopAsync (bool animated) public static IVisualElementRenderer GetRenderer (VisualElement bindable)
{ {
throw new NotImplementedException (); return (IVisualElementRenderer)bindable.GetValue (RendererProperty);
} }
Task<Page> INavigation.PopModalAsync () public static void SetRenderer (VisualElement bindable, IVisualElementRenderer value)
{ {
throw new NotImplementedException (); bindable.SetValue (RendererProperty, value);
} }
Task<Page> INavigation.PopModalAsync (bool animated) protected override void OnBindingContextChanged ()
{ {
throw new NotImplementedException (); SetInheritedBindingContext (Page, BindingContext);
}
Task INavigation.PopToRootAsync () base.OnBindingContextChanged ();
{ }
throw new NotImplementedException ();
}
Task INavigation.PopToRootAsync (bool animated) public SizeRequest GetNativeSize (VisualElement view, double widthConstraint, double heightConstraint)
{ {
throw new NotImplementedException (); return new SizeRequest (new Size (100, 100));
} }
Task INavigation.PushAsync (Page page) public void SetPage (Page newRoot)
{ {
throw new NotImplementedException (); if (newRoot == null)
} return;
if (Page != null)
throw new NotImplementedException ();
Page = newRoot;
Task INavigation.PushAsync (Page page, bool animated) Page.Platform = this;
{ AddChild (Page);
throw new NotImplementedException ();
}
Task INavigation.PushModalAsync (Page page) Page.DescendantRemoved += HandleChildRemoved;
{
throw new NotImplementedException ();
}
Task INavigation.PushModalAsync (Page page, bool animated) Application.Current.NavigationProxy.Inner = this;
{ }
throw new NotImplementedException ();
}
void INavigation.RemovePage (Page page) void HandleChildRemoved (object sender, ElementEventArgs e)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
}
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.AppendChild (viewRenderer.NativeView);
viewRenderer.SetElementSize (new Size (640, 480));
}
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

@ -3,10 +3,10 @@ using Xamarin.Forms;
namespace Ooui.Forms.Renderers namespace Ooui.Forms.Renderers
{ {
public class ButtonRenderer : ViewRenderer<Xamarin.Forms.Button, Ooui.Button> public class ButtonRenderer : ViewRenderer<Xamarin.Forms.Button, Ooui.Button>
{ {
public ButtonRenderer() public ButtonRenderer ()
{ {
} }
} }
} }

View File

@ -3,10 +3,10 @@ using Xamarin.Forms;
namespace Ooui.Forms.Renderers namespace Ooui.Forms.Renderers
{ {
public class DefaultRenderer : VisualElementRenderer<VisualElement> public class DefaultRenderer : VisualElementRenderer<VisualElement>
{ {
public DefaultRenderer () public DefaultRenderer ()
{ {
} }
} }
} }

View File

@ -103,7 +103,7 @@ namespace Ooui.Forms.Renderers
if (Element == null || Control == null) if (Element == null || Control == null)
return; return;
var uiControl = Control as Ooui.Element; var uiControl = Control as Ooui.FormControl;
if (uiControl == null) if (uiControl == null)
return; return;
uiControl.IsDisabled = !Element.IsEnabled; uiControl.IsDisabled = !Element.IsEnabled;

View File

@ -19,8 +19,9 @@ namespace Ooui.Forms
{ {
readonly ConcurrentDictionary<string, object> values = readonly ConcurrentDictionary<string, object> values =
new ConcurrentDictionary<string, object> (); new ConcurrentDictionary<string, object> ();
#pragma warning disable 67
public event EventHandler<ResourcesChangedEventArgs> ValuesChanged; public event EventHandler<ResourcesChangedEventArgs> ValuesChanged;
#pragma warning restore 67
public bool TryGetValue (string key, out object value) public bool TryGetValue (string key, out object value)
{ {

View File

@ -6,145 +6,145 @@ using Xamarin.Forms;
namespace Ooui.Forms namespace Ooui.Forms
{ {
public class VisualElementRenderer<TElement> : Ooui.Element, IVisualElementRenderer where TElement : VisualElement public class VisualElementRenderer<TElement> : Ooui.Element, IVisualElementRenderer where TElement : VisualElement
{ {
bool disposedValue = false; // To detect redundant calls bool disposedValue = false; // To detect redundant calls
VisualElementTracker _tracker; VisualElementTracker _tracker;
readonly Color _defaultColor = Color.Clear; readonly Color _defaultColor = Color.Clear;
readonly PropertyChangedEventHandler _propertyChangedHandler; readonly PropertyChangedEventHandler _propertyChangedHandler;
public TElement Element { get; private set; } public TElement Element { get; private set; }
VisualElement IVisualElementRenderer.Element => Element; VisualElement IVisualElementRenderer.Element => Element;
public Element NativeView => this; public Element NativeView => this;
event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged { event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged {
add { _elementChangedHandlers.Add (value); } add { _elementChangedHandlers.Add (value); }
remove { _elementChangedHandlers.Remove (value); } remove { _elementChangedHandlers.Remove (value); }
} }
readonly List<EventHandler<VisualElementChangedEventArgs>> _elementChangedHandlers = readonly List<EventHandler<VisualElementChangedEventArgs>> _elementChangedHandlers =
new List<EventHandler<VisualElementChangedEventArgs>> (); new List<EventHandler<VisualElementChangedEventArgs>> ();
public VisualElementRenderer () : base ("div") public VisualElementRenderer () : base ("div")
{ {
_propertyChangedHandler = OnElementPropertyChanged; _propertyChangedHandler = OnElementPropertyChanged;
} }
protected virtual void OnElementChanged (ElementChangedEventArgs<TElement> e) protected virtual void OnElementChanged (ElementChangedEventArgs<TElement> e)
{ {
var args = new VisualElementChangedEventArgs (e.OldElement, e.NewElement); var args = new VisualElementChangedEventArgs (e.OldElement, e.NewElement);
for (int i = 0; i < _elementChangedHandlers.Count; i++) { for (int i = 0; i < _elementChangedHandlers.Count; i++) {
_elementChangedHandlers[i] (this, args); _elementChangedHandlers[i] (this, args);
} }
var changed = ElementChanged; var changed = ElementChanged;
if (changed != null) if (changed != null)
changed (this, e); changed (this, e);
} }
public event EventHandler<ElementChangedEventArgs<TElement>> ElementChanged; public event EventHandler<ElementChangedEventArgs<TElement>> ElementChanged;
void IVisualElementRenderer.SetElement (VisualElement element) void IVisualElementRenderer.SetElement (VisualElement element)
{ {
SetElement ((TElement)element); SetElement ((TElement)element);
} }
public void SetElement (TElement element) public void SetElement (TElement element)
{ {
var oldElement = Element; var oldElement = Element;
Element = element; Element = element;
if (oldElement != null) if (oldElement != null)
oldElement.PropertyChanged -= _propertyChangedHandler; oldElement.PropertyChanged -= _propertyChangedHandler;
if (element != null) { if (element != null) {
if (element.BackgroundColor != Xamarin.Forms.Color.Default || (oldElement != null && element.BackgroundColor != oldElement.BackgroundColor)) if (element.BackgroundColor != Xamarin.Forms.Color.Default || (oldElement != null && element.BackgroundColor != oldElement.BackgroundColor))
SetBackgroundColor (element.BackgroundColor); SetBackgroundColor (element.BackgroundColor);
if (_tracker == null) { if (_tracker == null) {
_tracker = new VisualElementTracker (this); _tracker = new VisualElementTracker (this);
_tracker.NativeControlUpdated += (sender, e) => UpdateNativeWidget (); _tracker.NativeControlUpdated += (sender, e) => UpdateNativeWidget ();
} }
//if (AutoPackage && _packager == null) { //if (AutoPackage && _packager == null) {
// _packager = new VisualElementPackager (this); // _packager = new VisualElementPackager (this);
// _packager.Load (); // _packager.Load ();
//} //}
//if (AutoTrack && _events == null) { //if (AutoTrack && _events == null) {
// _events = new EventTracker (this); // _events = new EventTracker (this);
// _events.LoadEvents (this); // _events.LoadEvents (this);
//} //}
element.PropertyChanged += _propertyChangedHandler; element.PropertyChanged += _propertyChangedHandler;
} }
OnElementChanged (new ElementChangedEventArgs<TElement> (oldElement, element)); OnElementChanged (new ElementChangedEventArgs<TElement> (oldElement, element));
if (element != null) if (element != null)
SendVisualElementInitialized (element, this); SendVisualElementInitialized (element, this);
if (Element != null && !string.IsNullOrEmpty (Element.AutomationId)) if (Element != null && !string.IsNullOrEmpty (Element.AutomationId))
SetAutomationId (Element.AutomationId); SetAutomationId (Element.AutomationId);
} }
public void SetElementSize (Size size) public void SetElementSize (Size size)
{ {
Xamarin.Forms.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));
} }
protected virtual void OnElementPropertyChanged (object sender, PropertyChangedEventArgs e) protected virtual void OnElementPropertyChanged (object sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName) { if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName) {
SetBackgroundColor (Element.BackgroundColor); SetBackgroundColor (Element.BackgroundColor);
} }
else if (e.PropertyName == Layout.IsClippedToBoundsProperty.PropertyName) { else if (e.PropertyName == Layout.IsClippedToBoundsProperty.PropertyName) {
//UpdateClipToBounds (); //UpdateClipToBounds ();
} }
} }
protected virtual void OnRegisterEffect (PlatformEffect effect) protected virtual void OnRegisterEffect (PlatformEffect effect)
{ {
//effect.Container = this; //effect.Container = this;
} }
protected virtual void SetAutomationId (string id) protected virtual void SetAutomationId (string id)
{ {
} }
protected virtual void SetBackgroundColor (Xamarin.Forms.Color color) protected virtual void SetBackgroundColor (Xamarin.Forms.Color color)
{ {
if (color == Xamarin.Forms.Color.Default) if (color == Xamarin.Forms.Color.Default)
Style.BackgroundColor = _defaultColor; Style.BackgroundColor = _defaultColor;
else else
Style.BackgroundColor = color.ToOouiColor (); Style.BackgroundColor = color.ToOouiColor ();
} }
protected virtual void UpdateNativeWidget () protected virtual void UpdateNativeWidget ()
{ {
} }
protected virtual void SendVisualElementInitialized (VisualElement element, Element nativeView) protected virtual void SendVisualElementInitialized (VisualElement element, Element nativeView)
{ {
element.SendViewInitialized (nativeView); element.SendViewInitialized (nativeView);
} }
protected virtual void Dispose (bool disposing) protected virtual void Dispose (bool disposing)
{ {
if (!disposedValue) { if (!disposedValue) {
if (disposing) { if (disposing) {
} }
disposedValue = true; disposedValue = true;
} }
} }
public void Dispose () public void Dispose ()
{ {
Dispose (true); Dispose (true);
} }
} }
} }

View File

@ -6,213 +6,214 @@ using Xamarin.Forms.Internals;
namespace Ooui.Forms namespace Ooui.Forms
{ {
public class VisualElementTracker public class VisualElementTracker
{ {
readonly EventHandler<EventArg<VisualElement>> _batchCommittedHandler; readonly EventHandler<EventArg<VisualElement>> _batchCommittedHandler;
readonly PropertyChangedEventHandler _propertyChangedHandler; readonly PropertyChangedEventHandler _propertyChangedHandler;
readonly EventHandler _sizeChangedEventHandler; readonly EventHandler _sizeChangedEventHandler;
bool _disposed; bool _disposed;
VisualElement _element; VisualElement _element;
// Track these by hand because the calls down into iOS are too expensive // Track these by hand because the calls down into iOS are too expensive
bool _isInteractive; bool _isInteractive;
Rectangle _lastBounds; Rectangle _lastBounds;
#if !__MOBILE__ #if !__MOBILE__
Rectangle _lastParentBounds; Rectangle _lastParentBounds;
#endif #endif
int _updateCount; int _updateCount;
public VisualElementTracker (IVisualElementRenderer renderer) public VisualElementTracker (IVisualElementRenderer renderer)
{ {
if (renderer == null) if (renderer == null)
throw new ArgumentNullException (nameof (renderer)); throw new ArgumentNullException (nameof (renderer));
_propertyChangedHandler = HandlePropertyChanged; _propertyChangedHandler = HandlePropertyChanged;
_sizeChangedEventHandler = HandleSizeChanged; _sizeChangedEventHandler = HandleSizeChanged;
_batchCommittedHandler = HandleRedrawNeeded; _batchCommittedHandler = HandleRedrawNeeded;
Renderer = renderer; Renderer = renderer;
renderer.ElementChanged += OnRendererElementChanged; renderer.ElementChanged += OnRendererElementChanged;
SetElement (null, renderer.Element); SetElement (null, renderer.Element);
} }
IVisualElementRenderer Renderer { get; set; } IVisualElementRenderer Renderer { get; set; }
public void Dispose () public void Dispose ()
{ {
Dispose (true); Dispose (true);
} }
public event EventHandler NativeControlUpdated; public event EventHandler NativeControlUpdated;
protected virtual void Dispose (bool disposing) protected virtual void Dispose (bool disposing)
{ {
if (_disposed) if (_disposed)
return; return;
_disposed = true; _disposed = true;
if (disposing) { if (disposing) {
SetElement (_element, null); SetElement (_element, null);
Renderer.ElementChanged -= OnRendererElementChanged; Renderer.ElementChanged -= OnRendererElementChanged;
Renderer = null; Renderer = null;
} }
} }
void HandlePropertyChanged (object sender, PropertyChangedEventArgs e) void HandlePropertyChanged (object sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == VisualElement.XProperty.PropertyName || e.PropertyName == VisualElement.YProperty.PropertyName || e.PropertyName == VisualElement.WidthProperty.PropertyName || if (e.PropertyName == VisualElement.XProperty.PropertyName || e.PropertyName == VisualElement.YProperty.PropertyName || e.PropertyName == VisualElement.WidthProperty.PropertyName ||
e.PropertyName == VisualElement.HeightProperty.PropertyName || e.PropertyName == VisualElement.AnchorXProperty.PropertyName || e.PropertyName == VisualElement.AnchorYProperty.PropertyName || e.PropertyName == VisualElement.HeightProperty.PropertyName || e.PropertyName == VisualElement.AnchorXProperty.PropertyName || e.PropertyName == VisualElement.AnchorYProperty.PropertyName ||
e.PropertyName == VisualElement.TranslationXProperty.PropertyName || e.PropertyName == VisualElement.TranslationYProperty.PropertyName || e.PropertyName == VisualElement.ScaleProperty.PropertyName || e.PropertyName == VisualElement.TranslationXProperty.PropertyName || e.PropertyName == VisualElement.TranslationYProperty.PropertyName || e.PropertyName == VisualElement.ScaleProperty.PropertyName ||
e.PropertyName == VisualElement.RotationProperty.PropertyName || e.PropertyName == VisualElement.RotationXProperty.PropertyName || e.PropertyName == VisualElement.RotationYProperty.PropertyName || e.PropertyName == VisualElement.RotationProperty.PropertyName || e.PropertyName == VisualElement.RotationXProperty.PropertyName || e.PropertyName == VisualElement.RotationYProperty.PropertyName ||
e.PropertyName == VisualElement.IsVisibleProperty.PropertyName || e.PropertyName == VisualElement.IsEnabledProperty.PropertyName || e.PropertyName == VisualElement.IsVisibleProperty.PropertyName || e.PropertyName == VisualElement.IsEnabledProperty.PropertyName ||
e.PropertyName == VisualElement.InputTransparentProperty.PropertyName || e.PropertyName == VisualElement.OpacityProperty.PropertyName) e.PropertyName == VisualElement.InputTransparentProperty.PropertyName || e.PropertyName == VisualElement.OpacityProperty.PropertyName)
UpdateNativeControl (); // poorly optimized UpdateNativeControl (); // poorly optimized
} }
void HandleRedrawNeeded (object sender, EventArgs e) void HandleRedrawNeeded (object sender, EventArgs e)
{ {
UpdateNativeControl (); UpdateNativeControl ();
} }
void HandleSizeChanged (object sender, EventArgs e) void HandleSizeChanged (object sender, EventArgs e)
{ {
UpdateNativeControl (); UpdateNativeControl ();
} }
void OnRendererElementChanged (object s, VisualElementChangedEventArgs e) void OnRendererElementChanged (object s, VisualElementChangedEventArgs e)
{ {
if (_element == e.NewElement) if (_element == e.NewElement)
return; return;
SetElement (_element, e.NewElement); SetElement (_element, e.NewElement);
} }
void OnUpdateNativeControl () void OnUpdateNativeControl ()
{ {
var view = Renderer.Element; var view = Renderer.Element;
var uiview = Renderer.NativeView; var uiview = Renderer.NativeView;
if (view == null || view.Batched) if (view == null || view.Batched)
return; return;
var shouldInteract = !view.InputTransparent && view.IsEnabled; var shouldInteract = !view.InputTransparent && view.IsEnabled;
if (_isInteractive != shouldInteract) { if (_isInteractive != shouldInteract) {
_isInteractive = shouldInteract; _isInteractive = shouldInteract;
} }
var boundsChanged = _lastBounds != view.Bounds; var boundsChanged = _lastBounds != view.Bounds;
var viewParent = view.RealParent as VisualElement; var viewParent = view.RealParent as VisualElement;
var parentBoundsChanged = _lastParentBounds != (viewParent == null ? Rectangle.Zero : viewParent.Bounds); var parentBoundsChanged = _lastParentBounds != (viewParent == null ? Rectangle.Zero : viewParent.Bounds);
var thread = !boundsChanged; var thread = !boundsChanged;
var anchorX = (float)view.AnchorX; var anchorX = (float)view.AnchorX;
var anchorY = (float)view.AnchorY; var anchorY = (float)view.AnchorY;
var translationX = (float)view.TranslationX; var translationX = (float)view.TranslationX;
var translationY = (float)view.TranslationY; var translationY = (float)view.TranslationY;
var rotationX = (float)view.RotationX; var rotationX = (float)view.RotationX;
var rotationY = (float)view.RotationY; var rotationY = (float)view.RotationY;
var rotation = (float)view.Rotation; var rotation = (float)view.Rotation;
var scale = (float)view.Scale; var scale = (float)view.Scale;
var width = (float)view.Width; var width = (float)view.Width;
var height = (float)view.Height; var height = (float)view.Height;
var x = (float)view.X; var x = (float)view.X;
var y = (float)view.Y; var y = (float)view.Y;
var opacity = (float)view.Opacity; var opacity = (float)view.Opacity;
var isVisible = view.IsVisible; var isVisible = view.IsVisible;
var updateTarget = Interlocked.Increment (ref _updateCount); var updateTarget = Interlocked.Increment (ref _updateCount);
if (updateTarget != _updateCount) if (updateTarget != _updateCount)
return; return;
var parent = view.RealParent; var parent = view.RealParent;
if (isVisible && uiview.IsHidden) { if (isVisible && uiview.IsHidden) {
uiview.IsHidden = false; uiview.IsHidden = false;
} }
if (!isVisible && !uiview.IsHidden) { if (!isVisible && !uiview.IsHidden) {
uiview.IsHidden = true; uiview.IsHidden = true;
} }
parentBoundsChanged = true; parentBoundsChanged = true;
bool shouldUpdate = width > 0 && height > 0 && parent != null && (boundsChanged || parentBoundsChanged); bool shouldUpdate = width > 0 && height > 0 && parent != null && (boundsChanged || parentBoundsChanged);
if (shouldUpdate) { if (shouldUpdate) {
var visualParent = parent as VisualElement; var visualParent = parent as VisualElement;
float newY = visualParent == null ? y : Math.Max (0, (float)(visualParent.Height - y - view.Height)); float newY = visualParent == null ? y : Math.Max (0, (float)(visualParent.Height - y - view.Height));
var target = new Rectangle (x, newY, width, height); var target = new Rectangle (x, newY, width, height);
uiview.Style.Left = x; uiview.Style.Position = "absolute";
uiview.Style.Top = newY; uiview.Style.Left = x;
uiview.Style.Width = width; uiview.Style.Top = newY;
uiview.Style.Height = height; uiview.Style.Right = x + width;
} uiview.Style.Bottom = newY + height;
else if (width <= 0 || height <= 0) { }
return; else if (width <= 0 || height <= 0) {
} return;
uiview.Style.Opacity = opacity; }
uiview.Style.Opacity = opacity;
//var transform = 0; //var transform = 0;
//const double epsilon = 0.001; //const double epsilon = 0.001;
//caLayer.AnchorPoint = new PointF (anchorX - 0.5f, anchorY - 0.5f); //caLayer.AnchorPoint = new PointF (anchorX - 0.5f, anchorY - 0.5f);
//// position is relative to anchor point //// position is relative to anchor point
//if (Math.Abs (anchorX - .5) > epsilon) //if (Math.Abs (anchorX - .5) > epsilon)
// transform = transform.Translate ((anchorX - .5f) * width, 0, 0); // transform = transform.Translate ((anchorX - .5f) * width, 0, 0);
//if (Math.Abs (anchorY - .5) > epsilon) //if (Math.Abs (anchorY - .5) > epsilon)
// transform = transform.Translate (0, (anchorY - .5f) * height, 0); // transform = transform.Translate (0, (anchorY - .5f) * height, 0);
//if (Math.Abs (translationX) > epsilon || Math.Abs (translationY) > epsilon) //if (Math.Abs (translationX) > epsilon || Math.Abs (translationY) > epsilon)
// transform = transform.Translate (translationX, translationY, 0); // transform = transform.Translate (translationX, translationY, 0);
//if (Math.Abs (scale - 1) > epsilon) //if (Math.Abs (scale - 1) > epsilon)
// transform = transform.Scale (scale); // transform = transform.Scale (scale);
//// not just an optimization, iOS will not "pixel align" a view which has m34 set //// not just an optimization, iOS will not "pixel align" a view which has m34 set
//if (Math.Abs (rotationY % 180) > epsilon || Math.Abs (rotationX % 180) > epsilon) //if (Math.Abs (rotationY % 180) > epsilon || Math.Abs (rotationX % 180) > epsilon)
// transform.m34 = 1.0f / -400f; // transform.m34 = 1.0f / -400f;
//if (Math.Abs (rotationX % 360) > epsilon) //if (Math.Abs (rotationX % 360) > epsilon)
// transform = transform.Rotate (rotationX * (float)Math.PI / 180.0f, 1.0f, 0.0f, 0.0f); // transform = transform.Rotate (rotationX * (float)Math.PI / 180.0f, 1.0f, 0.0f, 0.0f);
//if (Math.Abs (rotationY % 360) > epsilon) //if (Math.Abs (rotationY % 360) > epsilon)
// transform = transform.Rotate (rotationY * (float)Math.PI / 180.0f, 0.0f, 1.0f, 0.0f); // transform = transform.Rotate (rotationY * (float)Math.PI / 180.0f, 0.0f, 1.0f, 0.0f);
//transform = transform.Rotate (rotation * (float)Math.PI / 180.0f, 0.0f, 0.0f, 1.0f); //transform = transform.Rotate (rotation * (float)Math.PI / 180.0f, 0.0f, 0.0f, 1.0f);
//caLayer.Transform = transform; //caLayer.Transform = transform;
_lastBounds = view.Bounds; _lastBounds = view.Bounds;
_lastParentBounds = viewParent?.Bounds ?? Rectangle.Zero; _lastParentBounds = viewParent?.Bounds ?? Rectangle.Zero;
} }
void SetElement (VisualElement oldElement, VisualElement newElement) void SetElement (VisualElement oldElement, VisualElement newElement)
{ {
if (oldElement != null) { if (oldElement != null) {
oldElement.PropertyChanged -= _propertyChangedHandler; oldElement.PropertyChanged -= _propertyChangedHandler;
oldElement.SizeChanged -= _sizeChangedEventHandler; oldElement.SizeChanged -= _sizeChangedEventHandler;
oldElement.BatchCommitted -= _batchCommittedHandler; oldElement.BatchCommitted -= _batchCommittedHandler;
} }
_element = newElement; _element = newElement;
if (newElement != null) { if (newElement != null) {
newElement.BatchCommitted += _batchCommittedHandler; newElement.BatchCommitted += _batchCommittedHandler;
newElement.SizeChanged += _sizeChangedEventHandler; newElement.SizeChanged += _sizeChangedEventHandler;
newElement.PropertyChanged += _propertyChangedHandler; newElement.PropertyChanged += _propertyChangedHandler;
UpdateNativeControl (); UpdateNativeControl ();
} }
} }
void UpdateNativeControl () void UpdateNativeControl ()
{ {
if (_disposed) if (_disposed)
return; return;
OnUpdateNativeControl (); OnUpdateNativeControl ();
NativeControlUpdated?.Invoke (this, EventArgs.Empty); NativeControlUpdated?.Invoke (this, EventArgs.Empty);
} }
} }
} }

View File

@ -79,6 +79,7 @@ Global
$1.FileWidth = 128 $1.FileWidth = 128
$1.NoTabsAfterNonTabs = True $1.NoTabsAfterNonTabs = True
$1.scope = text/x-csharp $1.scope = text/x-csharp
$1.TabsToSpaces = True
$0.CSharpFormattingPolicy = $2 $0.CSharpFormattingPolicy = $2
$2.scope = text/x-csharp $2.scope = text/x-csharp
$2.NewLinesForBracesInProperties = False $2.NewLinesForBracesInProperties = False

View File

@ -25,12 +25,6 @@ namespace Ooui
set => SetProperty (ref hidden, value, "hidden"); set => SetProperty (ref hidden, value, "hidden");
} }
bool disabled = false;
public bool IsDisabled {
get => disabled;
set => SetProperty (ref disabled, value, "disabled");
}
public event TargetEventHandler Clicked { public event TargetEventHandler Clicked {
add => AddEventListener ("click", value); add => AddEventListener ("click", value);
remove => RemoveEventListener ("click", value); remove => RemoveEventListener ("click", value);

View File

@ -11,7 +11,7 @@ namespace Ooui
readonly Dictionary<string, Value> properties = readonly Dictionary<string, Value> properties =
new Dictionary<string, Value> (); new Dictionary<string, Value> ();
public Value AlignSelf { public Value AlignSelf {
get => this["align-self"]; get => this["align-self"];
set => this["align-self"] = value; set => this["align-self"] = value;
@ -232,10 +232,10 @@ namespace Ooui
} }
} }
public Value Opacity { public Value Opacity {
get => this["opacity"]; get => this["opacity"];
set => this["opacity"] = value; set => this["opacity"] = value;
} }
public Value Order { public Value Order {
get => this["order"]; get => this["order"];
@ -272,6 +272,11 @@ namespace Ooui
} }
} }
public Value Position {
get => this["position"];
set => this["position"] = value;
}
public Value Right { public Value Right {
get => this["right"]; get => this["right"];
set => this["right"] = value; set => this["right"] = value;
@ -307,8 +312,7 @@ namespace Ooui
set => this["width"] = value; set => this["width"] = value;
} }
public Value this [string propertyName] public Value this[string propertyName] {
{
get { get {
lock (properties) { lock (properties) {
Value p; Value p;