diff --git a/csharp/Facebook.Yoga/Native.cs b/csharp/Facebook.Yoga/Native.cs index 2f98b960..83efce85 100644 --- a/csharp/Facebook.Yoga/Native.cs +++ b/csharp/Facebook.Yoga/Native.cs @@ -111,6 +111,13 @@ namespace Facebook.Yoga [return: MarshalAs(UnmanagedType.I1)] 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 #region YG_NODE_STYLE_PROPERTY diff --git a/csharp/Facebook.Yoga/YogaLogger.cs b/csharp/Facebook.Yoga/YogaLogger.cs index e5d79b79..68d946e6 100644 --- a/csharp/Facebook.Yoga/YogaLogger.cs +++ b/csharp/Facebook.Yoga/YogaLogger.cs @@ -8,17 +8,14 @@ */ using System; -using System.Runtime.InteropServices; namespace Facebook.Yoga { internal static class YogaLogger { - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void Func(YogaLogLevel level, string message); private static bool _initialized; - private static Func _managedLogger = null; public static Func Logger = null; @@ -26,20 +23,27 @@ namespace Facebook.Yoga { if (!_initialized) { - _managedLogger = (level, message) => { - if (Logger != null) - { - Logger(level, message); - } - if (level == YogaLogLevel.Error) - { - throw new InvalidOperationException(message); - } - }; - Native.YGInteropSetLogger(_managedLogger); + Native.YGInteropSetLogger(LoggerInternal); _initialized = true; } } + +#if __IOS__ + [ObjCRuntime.MonoPInvokeCallback(typeof(Func))] +#endif + public static void LoggerInternal(YogaLogLevel level, string message) + { + if (Logger != null) + { + Logger(level, message); + } + + if (level == YogaLogLevel.Error) + { + throw new InvalidOperationException(message); + } + } + } } diff --git a/csharp/Facebook.Yoga/YogaNode.cs b/csharp/Facebook.Yoga/YogaNode.cs index cb737c99..0cfdb4c5 100644 --- a/csharp/Facebook.Yoga/YogaNode.cs +++ b/csharp/Facebook.Yoga/YogaNode.cs @@ -10,6 +10,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.InteropServices; using System.Text; namespace Facebook.Yoga @@ -544,7 +545,7 @@ namespace Facebook.Yoga { while (_children.Count > 0) { - RemoveAt(_children.Count-1); + RemoveAt(_children.Count - 1); } } } @@ -558,6 +559,10 @@ namespace Facebook.Yoga { _measureFunction = measureFunction; _ygMeasureFunc = measureFunction != null ? MeasureInternal : (YogaMeasureFunc)null; + + var handle = GCHandle.Alloc(this); + Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle)); + Native.YGNodeSetMeasureFunc(_ygNode, _ygMeasureFunc); } @@ -565,6 +570,10 @@ namespace Facebook.Yoga { _baselineFunction = baselineFunction; _ygBaselineFunc = baselineFunction != null ? BaselineInternal : (YogaBaselineFunc)null; + + var handle = GCHandle.Alloc(this); + Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle)); + Native.YGNodeSetBaselineFunc(_ygNode, _ygBaselineFunc); } @@ -577,37 +586,55 @@ namespace Facebook.Yoga Native.YGNodeStyleGetDirection(_ygNode)); } - private YogaSize MeasureInternal( +#if __IOS__ + [ObjCRuntime.MonoPInvokeCallback(typeof(YogaMeasureFunc))] +#endif + private static YogaSize MeasureInternal( IntPtr node, float width, YogaMeasureMode widthMode, float height, 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."); } - 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."); } - return _baselineFunction(this, width, height); + return baselineFunction(yogaNode, width, height); } public string Print(YogaPrintOptions options = - YogaPrintOptions.Layout|YogaPrintOptions.Style|YogaPrintOptions.Children) + YogaPrintOptions.Layout | YogaPrintOptions.Style | YogaPrintOptions.Children) { StringBuilder sb = new StringBuilder(); YogaLogger.Func orig = YogaLogger.Logger; - YogaLogger.Logger = (level, message) => {sb.Append(message);}; + YogaLogger.Logger = (level, message) => { sb.Append(message); }; Native.YGNodePrint(_ygNode, options); YogaLogger.Logger = orig; return sb.ToString();