[csharp] Implement static methods for callbacks so they work on aot on iOS, use YogaRef to store pointer to managed YogaNode

This commit is contained in:
Rui Marinho
2017-02-10 15:45:15 +00:00
parent b7fbe1c986
commit f90633cec5
3 changed files with 65 additions and 9 deletions

View File

@@ -111,6 +111,13 @@ namespace Facebook.Yoga
[return: MarshalAs(UnmanagedType.I1)] [return: MarshalAs(UnmanagedType.I1)]
public static extern bool YGNodeGetHasNewLayout(YGNodeHandle node); public static extern bool YGNodeGetHasNewLayout(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeSetContext(YGNodeHandle node, IntPtr context);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr YGNodeGetContext(IntPtr node);
#endregion #endregion
#region YG_NODE_STYLE_PROPERTY #region YG_NODE_STYLE_PROPERTY

View File

@@ -37,9 +37,31 @@ namespace Facebook.Yoga
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }
}; };
#if __IOS__
Native.YGInteropSetLogger(ManagedLogger);
#else
Native.YGInteropSetLogger(_managedLogger); Native.YGInteropSetLogger(_managedLogger);
#endif
_initialized = true; _initialized = true;
} }
} }
#if __IOS__
delegate void ManagedLoggerCallback(YogaLogLevel level, string message);
[ObjCRuntime.MonoPInvokeCallback(typeof(ManagedLoggerCallback))]
public static void ManagedLogger(YogaLogLevel level, string message)
{
if (Logger != null)
{
Logger(level, message);
}
if (level == YogaLogLevel.Error)
{
throw new InvalidOperationException(message);
}
}
#endif
} }
} }

View File

@@ -10,6 +10,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
namespace Facebook.Yoga namespace Facebook.Yoga
@@ -532,7 +533,7 @@ namespace Facebook.Yoga
{ {
while (_children.Count > 0) while (_children.Count > 0)
{ {
RemoveAt(_children.Count-1); RemoveAt(_children.Count - 1);
} }
} }
} }
@@ -546,6 +547,10 @@ namespace Facebook.Yoga
{ {
_measureFunction = measureFunction; _measureFunction = measureFunction;
_ygMeasureFunc = measureFunction != null ? MeasureInternal : (YogaMeasureFunc)null; _ygMeasureFunc = measureFunction != null ? MeasureInternal : (YogaMeasureFunc)null;
var handle = GCHandle.Alloc(this);
Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle));
Native.YGNodeSetMeasureFunc(_ygNode, _ygMeasureFunc); Native.YGNodeSetMeasureFunc(_ygNode, _ygMeasureFunc);
} }
@@ -553,6 +558,10 @@ namespace Facebook.Yoga
{ {
_baselineFunction = baselineFunction; _baselineFunction = baselineFunction;
_ygBaselineFunc = baselineFunction != null ? BaselineInternal : (YogaBaselineFunc)null; _ygBaselineFunc = baselineFunction != null ? BaselineInternal : (YogaBaselineFunc)null;
var handle = GCHandle.Alloc(this);
Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle));
Native.YGNodeSetBaselineFunc(_ygNode, _ygBaselineFunc); Native.YGNodeSetBaselineFunc(_ygNode, _ygBaselineFunc);
} }
@@ -565,37 +574,55 @@ namespace Facebook.Yoga
Native.YGNodeStyleGetDirection(_ygNode)); Native.YGNodeStyleGetDirection(_ygNode));
} }
private YogaSize MeasureInternal( #if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(YogaMeasureFunc))]
#endif
private static YogaSize MeasureInternal(
IntPtr node, IntPtr node,
float width, float width,
YogaMeasureMode widthMode, YogaMeasureMode widthMode,
float height, float height,
YogaMeasureMode heightMode) YogaMeasureMode heightMode)
{ {
if (_measureFunction == null)
var yogaNodePointer = Native.YGNodeGetContext(node);
YogaNode yogaNode = GCHandle.FromIntPtr(yogaNodePointer).Target as YogaNode;
var measureFunction = yogaNode._measureFunction;
if (measureFunction == null)
{ {
throw new InvalidOperationException("Measure function is not defined."); throw new InvalidOperationException("Measure function is not defined.");
} }
return _measureFunction(this, width, widthMode, height, heightMode); return measureFunction(yogaNode, width, widthMode, height, heightMode);
} }
private float BaselineInternal(IntPtr node, float width, float height)
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(YogaBaselineFunc))]
#endif
private static float BaselineInternal(IntPtr node, float width, float height)
{ {
if (_baselineFunction == null) var yogaNodePointer = Native.YGNodeGetContext(node);
YogaNode yogaNode = GCHandle.FromIntPtr(yogaNodePointer).Target as YogaNode;
var baselineFunction = yogaNode._baselineFunction;
if (baselineFunction == null)
{ {
throw new InvalidOperationException("Baseline function is not defined."); throw new InvalidOperationException("Baseline function is not defined.");
} }
return _baselineFunction(this, width, height); return baselineFunction(yogaNode, width, height);
} }
public string Print(YogaPrintOptions options = public string Print(YogaPrintOptions options =
YogaPrintOptions.Layout|YogaPrintOptions.Style|YogaPrintOptions.Children) YogaPrintOptions.Layout | YogaPrintOptions.Style | YogaPrintOptions.Children)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
YogaLogger.Func orig = YogaLogger.Logger; YogaLogger.Func orig = YogaLogger.Logger;
YogaLogger.Logger = (level, message) => {sb.Append(message);}; YogaLogger.Logger = (level, message) => { sb.Append(message); };
Native.YGNodePrint(_ygNode, options); Native.YGNodePrint(_ygNode, options);
YogaLogger.Logger = orig; YogaLogger.Logger = orig;
return sb.ToString(); return sb.ToString();