From 2643b96589018fa378d043a619ecc5ee98755200 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 19 Feb 2019 11:15:11 -0800 Subject: [PATCH] Extract abstract class `YogaNode` Summary: @public Here, we extract an abstract class from `YogaNode`, in order to allow for experimentation with different implementations. The reason for not choosing an interface is to keep ABI compatibility for `YogaNode.create()`. Reviewed By: pasqualeanatriello Differential Revision: D14044990 fbshipit-source-id: f8eb246338b55f34f0401198c0655abfcb7c9f37 --- java/com/facebook/yoga/YogaConfig.java | 4 +- java/com/facebook/yoga/YogaNode.java | 951 ++++-------------- java/com/facebook/yoga/YogaNodeJNI.java | 800 +++++++++++++++ java/jni/YGJNI.cpp | 12 +- .../tests/com/facebook/yoga/YogaNodeTest.java | 16 +- 5 files changed, 996 insertions(+), 787 deletions(-) create mode 100644 java/com/facebook/yoga/YogaNodeJNI.java diff --git a/java/com/facebook/yoga/YogaConfig.java b/java/com/facebook/yoga/YogaConfig.java index 40de7d2c..a55f5c70 100644 --- a/java/com/facebook/yoga/YogaConfig.java +++ b/java/com/facebook/yoga/YogaConfig.java @@ -106,7 +106,7 @@ public class YogaConfig { } @DoNotStrip - private final YogaNode cloneNode(YogaNode oldNode, YogaNode parent, int childIndex) { - return mYogaNodeCloneFunction.cloneNode(oldNode, parent, childIndex); + private final YogaNodeJNI cloneNode(YogaNodeJNI oldNode, YogaNodeJNI parent, int childIndex) { + return (YogaNodeJNI) mYogaNodeCloneFunction.cloneNode(oldNode, parent, childIndex); } } diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index b50f01d3..e5201297 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -6,250 +6,30 @@ */ package com.facebook.yoga; -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.soloader.SoLoader; -import java.util.ArrayList; -import java.util.List; import javax.annotation.Nullable; -@DoNotStrip -public class YogaNode implements Cloneable { - - static { - SoLoader.loadLibrary("yoga"); +public abstract class YogaNode { + public static YogaNode create() { + return new YogaNodeJNI(); } - /** - * Get native instance count. Useful for testing only. - */ - static native int jni_YGNodeGetInstanceCount(); - - private YogaNode mOwner; - @Nullable private List mChildren; - private YogaMeasureFunction mMeasureFunction; - private YogaBaselineFunction mBaselineFunction; - private long mNativePointer; - private Object mData; - - /* Those flags needs be in sync with YGJNI.cpp */ - private static final int MARGIN = 1; - private static final int PADDING = 2; - private static final int BORDER = 4; - - @DoNotStrip - private int mEdgeSetFlag = 0; - - private boolean mHasSetPosition = false; - - @DoNotStrip - private float mWidth = YogaConstants.UNDEFINED; - @DoNotStrip - private float mHeight = YogaConstants.UNDEFINED; - @DoNotStrip - private float mTop = YogaConstants.UNDEFINED; - @DoNotStrip - private float mLeft = YogaConstants.UNDEFINED; - @DoNotStrip - private float mMarginLeft = 0; - @DoNotStrip - private float mMarginTop = 0; - @DoNotStrip - private float mMarginRight = 0; - @DoNotStrip - private float mMarginBottom = 0; - @DoNotStrip - private float mPaddingLeft = 0; - @DoNotStrip - private float mPaddingTop = 0; - @DoNotStrip - private float mPaddingRight = 0; - @DoNotStrip - private float mPaddingBottom = 0; - @DoNotStrip - private float mBorderLeft = 0; - @DoNotStrip - private float mBorderTop = 0; - @DoNotStrip - private float mBorderRight = 0; - @DoNotStrip - private float mBorderBottom = 0; - @DoNotStrip - private int mLayoutDirection = 0; - @DoNotStrip - private boolean mHasNewLayout = true; - @DoNotStrip private boolean mDoesLegacyStretchFlagAffectsLayout = false; - - private native long jni_YGNodeNew(); - public YogaNode() { - mNativePointer = jni_YGNodeNew(); - if (mNativePointer == 0) { - throw new IllegalStateException("Failed to allocate native memory"); - } + public static YogaNode create(YogaConfig config) { + return new YogaNodeJNI(config); } - private native long jni_YGNodeNewWithConfig(long configPointer); - public YogaNode(YogaConfig config) { - mNativePointer = jni_YGNodeNewWithConfig(config.mNativePointer); - if (mNativePointer == 0) { - throw new IllegalStateException("Failed to allocate native memory"); - } - } + public abstract void reset(); - @Override - protected void finalize() throws Throwable { - try { - freeNatives(); - } finally { - super.finalize(); - } - } + public abstract int getChildCount(); - private static native void jni_YGNodeFree(long nativePointer); + public abstract YogaNode getChildAt(int i); - /* frees the native underlying YGNode. Useful for testing. */ - public void freeNatives() { - if (mNativePointer > 0) { - long nativePointer = mNativePointer; - mNativePointer = 0; - jni_YGNodeFree(nativePointer); - } - } + public abstract void addChildAt(YogaNode child, int i); - private static native void jni_YGNodeReset(long nativePointer); - public void reset() { - mEdgeSetFlag = 0; - mHasSetPosition = false; - mHasNewLayout = true; + public abstract void setIsReferenceBaseline(boolean isReferenceBaseline); - mWidth = YogaConstants.UNDEFINED; - mHeight = YogaConstants.UNDEFINED; - mTop = YogaConstants.UNDEFINED; - mLeft = YogaConstants.UNDEFINED; - mMarginLeft = 0; - mMarginTop = 0; - mMarginRight = 0; - mMarginBottom = 0; - mPaddingLeft = 0; - mPaddingTop = 0; - mPaddingRight = 0; - mPaddingBottom = 0; - mBorderLeft = 0; - mBorderTop = 0; - mBorderRight = 0; - mBorderBottom = 0; - mLayoutDirection = 0; + public abstract boolean isReferenceBaseline(); - mMeasureFunction = null; - mBaselineFunction = null; - mData = null; - mDoesLegacyStretchFlagAffectsLayout = false; - - jni_YGNodeReset(mNativePointer); - } - - public int getChildCount() { - return mChildren == null ? 0 : mChildren.size(); - } - - public YogaNode getChildAt(int i) { - if (mChildren == null) { - throw new IllegalStateException("YogaNode does not have children"); - } - return mChildren.get(i); - } - - private static native void jni_YGNodeInsertChild(long nativePointer, long childPointer, int index); - - public void addChildAt(YogaNode child, int i) { - if (child.mOwner != null) { - throw new IllegalStateException("Child already has a parent, it must be removed first."); - } - - if (mChildren == null) { - mChildren = new ArrayList<>(4); - } - mChildren.add(i, child); - child.mOwner = this; - jni_YGNodeInsertChild(mNativePointer, child.mNativePointer, i); - } - - private static native void jni_YGNodeSetIsReferenceBaseline(long nativePointer, boolean isReferenceBaseline); - - public void setIsReferenceBaseline(boolean isReferenceBaseline) { - jni_YGNodeSetIsReferenceBaseline(mNativePointer, isReferenceBaseline); - } - - private static native boolean jni_YGNodeIsReferenceBaseline(long nativePointer); - - public boolean isReferenceBaseline() { - return jni_YGNodeIsReferenceBaseline(mNativePointer); - } - - private static native void jni_YGNodeSetOwner(long nativePointer, long newOwnerNativePointer); - - private native long jni_YGNodeClone(long nativePointer, Object newNode); - - @Override - public YogaNode clone() { - try { - YogaNode clonedYogaNode = (YogaNode) super.clone(); - long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode); - - if (mChildren != null) { - for (YogaNode child : mChildren) { - YogaNode.jni_YGNodeSetOwner(child.mNativePointer, 0); - child.mOwner = null; - } - } - - clonedYogaNode.mNativePointer = clonedNativePointer; - clonedYogaNode.mOwner = null; - clonedYogaNode.mChildren = - mChildren != null ? (List) ((ArrayList) mChildren).clone() : null; - if (clonedYogaNode.mChildren != null) { - for (YogaNode child : clonedYogaNode.mChildren) { - child.mOwner = null; - } - } - return clonedYogaNode; - } catch (CloneNotSupportedException ex) { - // This class implements Cloneable, this should not happen - throw new RuntimeException(ex); - } - } - - public YogaNode cloneWithNewChildren() { - try { - YogaNode clonedYogaNode = (YogaNode) super.clone(); - long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode); - clonedYogaNode.mOwner = null; - clonedYogaNode.mNativePointer = clonedNativePointer; - clonedYogaNode.clearChildren(); - return clonedYogaNode; - } catch (CloneNotSupportedException ex) { - // This class implements Cloneable, this should not happen - throw new RuntimeException(ex); - } - } - - private static native void jni_YGNodeClearChildren(long nativePointer); - - private void clearChildren() { - mChildren = null; - jni_YGNodeClearChildren(mNativePointer); - } - - private static native void jni_YGNodeRemoveChild(long nativePointer, long childPointer); - public YogaNode removeChildAt(int i) { - if (mChildren == null) { - throw new IllegalStateException( - "Trying to remove a child of a YogaNode that does not have children"); - } - final YogaNode child = mChildren.remove(i); - child.mOwner = null; - jni_YGNodeRemoveChild(mNativePointer, child.mNativePointer); - return child; - } + public abstract YogaNode removeChildAt(int i); /** * @returns the {@link YogaNode} that owns this {@link YogaNode}. @@ -260,547 +40,176 @@ public class YogaNode implements Cloneable { * {@link YogaNode} is shared between two or more YogaTrees. */ @Nullable - public YogaNode getOwner() { - return mOwner; - } + public abstract YogaNode getOwner(); /** @deprecated Use #getOwner() instead. This will be removed in the next version. */ @Deprecated @Nullable - public YogaNode getParent() { - return getOwner(); - } - - public int indexOf(YogaNode child) { - return mChildren == null ? -1 : mChildren.indexOf(child); - } - - private static native void jni_YGNodeCalculateLayout(long nativePointer, float width, float height); - public void calculateLayout(float width, float height) { - jni_YGNodeCalculateLayout(mNativePointer, width, height); - } - - public boolean hasNewLayout() { - return mHasNewLayout; - } - - private static native void jni_YGNodeMarkDirty(long nativePointer); - public void dirty() { - jni_YGNodeMarkDirty(mNativePointer); - } - - private static native void jni_YGNodeMarkDirtyAndPropogateToDescendants(long nativePointer); - - public void dirtyAllDescendants() { - jni_YGNodeMarkDirtyAndPropogateToDescendants(mNativePointer); - } - - private static native boolean jni_YGNodeIsDirty(long nativePointer); - public boolean isDirty() { - return jni_YGNodeIsDirty(mNativePointer); - } - - private static native void jni_YGNodeCopyStyle(long dstNativePointer, long srcNativePointer); - public void copyStyle(YogaNode srcNode) { - jni_YGNodeCopyStyle(mNativePointer, srcNode.mNativePointer); - } - - public void markLayoutSeen() { - mHasNewLayout = false; - } - - private static native int jni_YGNodeStyleGetDirection(long nativePointer); - public YogaDirection getStyleDirection() { - return YogaDirection.fromInt(jni_YGNodeStyleGetDirection(mNativePointer)); - } - - private static native void jni_YGNodeStyleSetDirection(long nativePointer, int direction); - public void setDirection(YogaDirection direction) { - jni_YGNodeStyleSetDirection(mNativePointer, direction.intValue()); - } - - private static native int jni_YGNodeStyleGetFlexDirection(long nativePointer); - public YogaFlexDirection getFlexDirection() { - return YogaFlexDirection.fromInt(jni_YGNodeStyleGetFlexDirection(mNativePointer)); - } - - private static native void jni_YGNodeStyleSetFlexDirection(long nativePointer, int flexDirection); - public void setFlexDirection(YogaFlexDirection flexDirection) { - jni_YGNodeStyleSetFlexDirection(mNativePointer, flexDirection.intValue()); - } - - private static native int jni_YGNodeStyleGetJustifyContent(long nativePointer); - public YogaJustify getJustifyContent() { - return YogaJustify.fromInt(jni_YGNodeStyleGetJustifyContent(mNativePointer)); - } - - private static native void jni_YGNodeStyleSetJustifyContent(long nativePointer, int justifyContent); - public void setJustifyContent(YogaJustify justifyContent) { - jni_YGNodeStyleSetJustifyContent(mNativePointer, justifyContent.intValue()); - } - - private static native int jni_YGNodeStyleGetAlignItems(long nativePointer); - public YogaAlign getAlignItems() { - return YogaAlign.fromInt(jni_YGNodeStyleGetAlignItems(mNativePointer)); - } - - private static native void jni_YGNodeStyleSetAlignItems(long nativePointer, int alignItems); - public void setAlignItems(YogaAlign alignItems) { - jni_YGNodeStyleSetAlignItems(mNativePointer, alignItems.intValue()); - } - - private static native int jni_YGNodeStyleGetAlignSelf(long nativePointer); - public YogaAlign getAlignSelf() { - return YogaAlign.fromInt(jni_YGNodeStyleGetAlignSelf(mNativePointer)); - } - - private static native void jni_YGNodeStyleSetAlignSelf(long nativePointer, int alignSelf); - public void setAlignSelf(YogaAlign alignSelf) { - jni_YGNodeStyleSetAlignSelf(mNativePointer, alignSelf.intValue()); - } - - private static native int jni_YGNodeStyleGetAlignContent(long nativePointer); - public YogaAlign getAlignContent() { - return YogaAlign.fromInt(jni_YGNodeStyleGetAlignContent(mNativePointer)); - } - - private static native void jni_YGNodeStyleSetAlignContent(long nativePointer, int alignContent); - public void setAlignContent(YogaAlign alignContent) { - jni_YGNodeStyleSetAlignContent(mNativePointer, alignContent.intValue()); - } - - private static native int jni_YGNodeStyleGetPositionType(long nativePointer); - public YogaPositionType getPositionType() { - return YogaPositionType.fromInt(jni_YGNodeStyleGetPositionType(mNativePointer)); - } - - private static native void jni_YGNodeStyleSetPositionType(long nativePointer, int positionType); - public void setPositionType(YogaPositionType positionType) { - jni_YGNodeStyleSetPositionType(mNativePointer, positionType.intValue()); - } - - private static native void jni_YGNodeStyleSetFlexWrap(long nativePointer, int wrapType); - public void setWrap(YogaWrap flexWrap) { - jni_YGNodeStyleSetFlexWrap(mNativePointer, flexWrap.intValue()); - } - - private static native int jni_YGNodeStyleGetOverflow(long nativePointer); - public YogaOverflow getOverflow() { - return YogaOverflow.fromInt(jni_YGNodeStyleGetOverflow(mNativePointer)); - } - - private static native void jni_YGNodeStyleSetOverflow(long nativePointer, int overflow); - public void setOverflow(YogaOverflow overflow) { - jni_YGNodeStyleSetOverflow(mNativePointer, overflow.intValue()); - } - - private static native int jni_YGNodeStyleGetDisplay(long nativePointer); - public YogaDisplay getDisplay() { - return YogaDisplay.fromInt(jni_YGNodeStyleGetDisplay(mNativePointer)); - } - - private static native void jni_YGNodeStyleSetDisplay(long nativePointer, int display); - public void setDisplay(YogaDisplay display) { - jni_YGNodeStyleSetDisplay(mNativePointer, display.intValue()); - } - - private static native void jni_YGNodeStyleSetFlex(long nativePointer, float flex); - public void setFlex(float flex) { - jni_YGNodeStyleSetFlex(mNativePointer, flex); - } - - private static native float jni_YGNodeStyleGetFlexGrow(long nativePointer); - public float getFlexGrow() { - return jni_YGNodeStyleGetFlexGrow(mNativePointer); - } - - private static native void jni_YGNodeStyleSetFlexGrow(long nativePointer, float flexGrow); - public void setFlexGrow(float flexGrow) { - jni_YGNodeStyleSetFlexGrow(mNativePointer, flexGrow); - } - - private static native float jni_YGNodeStyleGetFlexShrink(long nativePointer); - public float getFlexShrink() { - return jni_YGNodeStyleGetFlexShrink(mNativePointer); - } - - private static native void jni_YGNodeStyleSetFlexShrink(long nativePointer, float flexShrink); - public void setFlexShrink(float flexShrink) { - jni_YGNodeStyleSetFlexShrink(mNativePointer, flexShrink); - } - - private static native Object jni_YGNodeStyleGetFlexBasis(long nativePointer); - public YogaValue getFlexBasis() { - return (YogaValue) jni_YGNodeStyleGetFlexBasis(mNativePointer); - } - - private static native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis); - public void setFlexBasis(float flexBasis) { - jni_YGNodeStyleSetFlexBasis(mNativePointer, flexBasis); - } - - private static native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent); - public void setFlexBasisPercent(float percent) { - jni_YGNodeStyleSetFlexBasisPercent(mNativePointer, percent); - } - - private static native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer); - public void setFlexBasisAuto() { - jni_YGNodeStyleSetFlexBasisAuto(mNativePointer); - } - - private static native Object jni_YGNodeStyleGetMargin(long nativePointer, int edge); - public YogaValue getMargin(YogaEdge edge) { - if (!((mEdgeSetFlag & MARGIN) == MARGIN)) { - return YogaValue.UNDEFINED; - } - return (YogaValue) jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()); - } - - private static native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin); - public void setMargin(YogaEdge edge, float margin) { - mEdgeSetFlag |= MARGIN; - jni_YGNodeStyleSetMargin(mNativePointer, edge.intValue(), margin); - } - - private static native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent); - public void setMarginPercent(YogaEdge edge, float percent) { - mEdgeSetFlag |= MARGIN; - jni_YGNodeStyleSetMarginPercent(mNativePointer, edge.intValue(), percent); - } - - private static native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge); - public void setMarginAuto(YogaEdge edge) { - mEdgeSetFlag |= MARGIN; - jni_YGNodeStyleSetMarginAuto(mNativePointer, edge.intValue()); - } - - private static native Object jni_YGNodeStyleGetPadding(long nativePointer, int edge); - public YogaValue getPadding(YogaEdge edge) { - if (!((mEdgeSetFlag & PADDING) == PADDING)) { - return YogaValue.UNDEFINED; - } - return (YogaValue) jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()); - } - - private static native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding); - public void setPadding(YogaEdge edge, float padding) { - mEdgeSetFlag |= PADDING; - jni_YGNodeStyleSetPadding(mNativePointer, edge.intValue(), padding); - } - - private static native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent); - public void setPaddingPercent(YogaEdge edge, float percent) { - mEdgeSetFlag |= PADDING; - jni_YGNodeStyleSetPaddingPercent(mNativePointer, edge.intValue(), percent); - } - - private static native float jni_YGNodeStyleGetBorder(long nativePointer, int edge); - public float getBorder(YogaEdge edge) { - if (!((mEdgeSetFlag & BORDER) == BORDER)) { - return YogaConstants.UNDEFINED; - } - return jni_YGNodeStyleGetBorder(mNativePointer, edge.intValue()); - } - - private static native void jni_YGNodeStyleSetBorder(long nativePointer, int edge, float border); - public void setBorder(YogaEdge edge, float border) { - mEdgeSetFlag |= BORDER; - jni_YGNodeStyleSetBorder(mNativePointer, edge.intValue(), border); - } - - private static native Object jni_YGNodeStyleGetPosition(long nativePointer, int edge); - public YogaValue getPosition(YogaEdge edge) { - if (!mHasSetPosition) { - return YogaValue.UNDEFINED; - } - return (YogaValue) jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()); - } - - private static native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position); - public void setPosition(YogaEdge edge, float position) { - mHasSetPosition = true; - jni_YGNodeStyleSetPosition(mNativePointer, edge.intValue(), position); - } - - private static native void jni_YGNodeStyleSetPositionPercent(long nativePointer, int edge, float percent); - public void setPositionPercent(YogaEdge edge, float percent) { - mHasSetPosition = true; - jni_YGNodeStyleSetPositionPercent(mNativePointer, edge.intValue(), percent); - } - - private static native Object jni_YGNodeStyleGetWidth(long nativePointer); - public YogaValue getWidth() { - return (YogaValue) jni_YGNodeStyleGetWidth(mNativePointer); - } - - private static native void jni_YGNodeStyleSetWidth(long nativePointer, float width); - public void setWidth(float width) { - jni_YGNodeStyleSetWidth(mNativePointer, width); - } - - private static native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent); - public void setWidthPercent(float percent) { - jni_YGNodeStyleSetWidthPercent(mNativePointer, percent); - } - - private static native void jni_YGNodeStyleSetWidthAuto(long nativePointer); - public void setWidthAuto() { - jni_YGNodeStyleSetWidthAuto(mNativePointer); - } - - private static native Object jni_YGNodeStyleGetHeight(long nativePointer); - public YogaValue getHeight() { - return (YogaValue) jni_YGNodeStyleGetHeight(mNativePointer); - } - - private static native void jni_YGNodeStyleSetHeight(long nativePointer, float height); - public void setHeight(float height) { - jni_YGNodeStyleSetHeight(mNativePointer, height); - } - - private static native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent); - public void setHeightPercent(float percent) { - jni_YGNodeStyleSetHeightPercent(mNativePointer, percent); - } - - private static native void jni_YGNodeStyleSetHeightAuto(long nativePointer); - public void setHeightAuto() { - jni_YGNodeStyleSetHeightAuto(mNativePointer); - } - - private static native Object jni_YGNodeStyleGetMinWidth(long nativePointer); - public YogaValue getMinWidth() { - return (YogaValue) jni_YGNodeStyleGetMinWidth(mNativePointer); - } - - private static native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth); - public void setMinWidth(float minWidth) { - jni_YGNodeStyleSetMinWidth(mNativePointer, minWidth); - } - - private static native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent); - public void setMinWidthPercent(float percent) { - jni_YGNodeStyleSetMinWidthPercent(mNativePointer, percent); - } - - private static native Object jni_YGNodeStyleGetMinHeight(long nativePointer); - public YogaValue getMinHeight() { - return (YogaValue) jni_YGNodeStyleGetMinHeight(mNativePointer); - } - - private static native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight); - public void setMinHeight(float minHeight) { - jni_YGNodeStyleSetMinHeight(mNativePointer, minHeight); - } - - private static native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent); - public void setMinHeightPercent(float percent) { - jni_YGNodeStyleSetMinHeightPercent(mNativePointer, percent); - } - - private static native Object jni_YGNodeStyleGetMaxWidth(long nativePointer); - public YogaValue getMaxWidth() { - return (YogaValue) jni_YGNodeStyleGetMaxWidth(mNativePointer); - } - - private static native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth); - public void setMaxWidth(float maxWidth) { - jni_YGNodeStyleSetMaxWidth(mNativePointer, maxWidth); - } - - private static native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent); - public void setMaxWidthPercent(float percent) { - jni_YGNodeStyleSetMaxWidthPercent(mNativePointer, percent); - } - - private static native Object jni_YGNodeStyleGetMaxHeight(long nativePointer); - public YogaValue getMaxHeight() { - return (YogaValue) jni_YGNodeStyleGetMaxHeight(mNativePointer); - } - - private static native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight); - public void setMaxHeight(float maxheight) { - jni_YGNodeStyleSetMaxHeight(mNativePointer, maxheight); - } - - private static native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent); - public void setMaxHeightPercent(float percent) { - jni_YGNodeStyleSetMaxHeightPercent(mNativePointer, percent); - } - - private static native float jni_YGNodeStyleGetAspectRatio(long nativePointer); - public float getAspectRatio() { - return jni_YGNodeStyleGetAspectRatio(mNativePointer); - } - - private static native void jni_YGNodeStyleSetAspectRatio(long nativePointer, float aspectRatio); - public void setAspectRatio(float aspectRatio) { - jni_YGNodeStyleSetAspectRatio(mNativePointer, aspectRatio); - } - - public float getLayoutX() { - return mLeft; - } - - public float getLayoutY() { - return mTop; - } - - public float getLayoutWidth() { - return mWidth; - } - - public float getLayoutHeight() { - return mHeight; - } - - public boolean getDoesLegacyStretchFlagAffectsLayout() { - return mDoesLegacyStretchFlagAffectsLayout; - } - - public float getLayoutMargin(YogaEdge edge) { - switch (edge) { - case LEFT: - return mMarginLeft; - case TOP: - return mMarginTop; - case RIGHT: - return mMarginRight; - case BOTTOM: - return mMarginBottom; - case START: - return getLayoutDirection() == YogaDirection.RTL ? mMarginRight : mMarginLeft; - case END: - return getLayoutDirection() == YogaDirection.RTL ? mMarginLeft : mMarginRight; - default: - throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands"); - } - } - - public float getLayoutPadding(YogaEdge edge) { - switch (edge) { - case LEFT: - return mPaddingLeft; - case TOP: - return mPaddingTop; - case RIGHT: - return mPaddingRight; - case BOTTOM: - return mPaddingBottom; - case START: - return getLayoutDirection() == YogaDirection.RTL ? mPaddingRight : mPaddingLeft; - case END: - return getLayoutDirection() == YogaDirection.RTL ? mPaddingLeft : mPaddingRight; - default: - throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands"); - } - } - - public float getLayoutBorder(YogaEdge edge) { - switch (edge) { - case LEFT: - return mBorderLeft; - case TOP: - return mBorderTop; - case RIGHT: - return mBorderRight; - case BOTTOM: - return mBorderBottom; - case START: - return getLayoutDirection() == YogaDirection.RTL ? mBorderRight : mBorderLeft; - case END: - return getLayoutDirection() == YogaDirection.RTL ? mBorderLeft : mBorderRight; - default: - throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands"); - } - } - - public YogaDirection getLayoutDirection() { - return YogaDirection.fromInt(mLayoutDirection); - } - - private static native void jni_YGNodeSetHasMeasureFunc(long nativePointer, boolean hasMeasureFunc); - public void setMeasureFunction(YogaMeasureFunction measureFunction) { - mMeasureFunction = measureFunction; - jni_YGNodeSetHasMeasureFunc(mNativePointer, measureFunction != null); - } - - // Implementation Note: Why this method needs to stay final - // - // We cache the jmethodid for this method in Yoga code. This means that even if a subclass - // were to override measure, we'd still call this implementation from layout code since the - // overriding method will have a different jmethodid. This is final to prevent that mistake. - @DoNotStrip - public final long measure(float width, int widthMode, float height, int heightMode) { - if (!isMeasureDefined()) { - throw new RuntimeException("Measure function isn't defined!"); - } - - return mMeasureFunction.measure( - this, - width, - YogaMeasureMode.fromInt(widthMode), - height, - YogaMeasureMode.fromInt(heightMode)); - } - - private static native void jni_YGNodeSetHasBaselineFunc(long nativePointer, boolean hasMeasureFunc); - public void setBaselineFunction(YogaBaselineFunction baselineFunction) { - mBaselineFunction = baselineFunction; - jni_YGNodeSetHasBaselineFunc(mNativePointer, baselineFunction != null); - } - - @DoNotStrip - public final float baseline(float width, float height) { - return mBaselineFunction.baseline(this, width, height); - } - - public boolean isMeasureDefined() { - return mMeasureFunction != null; - } - - public void setData(Object data) { - mData = data; - } - - public Object getData() { - return mData; - } - - private static native void jni_YGNodePrint(long nativePointer); - - /** - * Use the set logger (defaults to adb log) to print out the styles, children, and computed - * layout of the tree rooted at this node. - */ - public void print() { - jni_YGNodePrint(mNativePointer); - } - - /** - * This method replaces the child at childIndex position with the newNode received by parameter. - * This is different than calling removeChildAt and addChildAt because this method ONLY replaces - * the child in the mChildren datastructure. @DoNotStrip: called from JNI - * - * @return the nativePointer of the newNode {@linl YogaNode} - */ - @DoNotStrip - private final long replaceChild(YogaNode newNode, int childIndex) { - if (mChildren == null) { - throw new IllegalStateException("Cannot replace child. YogaNode does not have children"); - } - mChildren.remove(childIndex); - mChildren.add(childIndex, newNode); - newNode.mOwner = this; - return newNode.mNativePointer; - } - - public static YogaNode create() { - return new YogaNode(); - } - - public static YogaNode create(YogaConfig config) { - return new YogaNode(config); - } + public abstract YogaNode getParent(); + + public abstract int indexOf(YogaNode child); + + public abstract void calculateLayout(float width, float height); + + public abstract boolean hasNewLayout(); + + public abstract void dirty(); + + public abstract boolean isDirty(); + + public abstract void copyStyle(YogaNode srcNode); + + public abstract void markLayoutSeen(); + + public abstract YogaDirection getStyleDirection(); + + public abstract void setDirection(YogaDirection direction); + + public abstract YogaFlexDirection getFlexDirection(); + + public abstract void setFlexDirection(YogaFlexDirection flexDirection); + + public abstract YogaJustify getJustifyContent(); + + public abstract void setJustifyContent(YogaJustify justifyContent); + + public abstract YogaAlign getAlignItems(); + + public abstract void setAlignItems(YogaAlign alignItems); + + public abstract YogaAlign getAlignSelf(); + + public abstract void setAlignSelf(YogaAlign alignSelf); + + public abstract YogaAlign getAlignContent(); + + public abstract void setAlignContent(YogaAlign alignContent); + + public abstract YogaPositionType getPositionType(); + + public abstract void setPositionType(YogaPositionType positionType); + + public abstract void setWrap(YogaWrap flexWrap); + + public abstract YogaOverflow getOverflow(); + + public abstract void setOverflow(YogaOverflow overflow); + + public abstract YogaDisplay getDisplay(); + + public abstract void setDisplay(YogaDisplay display); + + public abstract void setFlex(float flex); + + public abstract float getFlexGrow(); + + public abstract void setFlexGrow(float flexGrow); + + public abstract float getFlexShrink(); + + public abstract void setFlexShrink(float flexShrink); + + public abstract YogaValue getFlexBasis(); + + public abstract void setFlexBasis(float flexBasis); + + public abstract void setFlexBasisPercent(float percent); + + public abstract void setFlexBasisAuto(); + + public abstract YogaValue getMargin(YogaEdge edge); + + public abstract void setMargin(YogaEdge edge, float margin); + + public abstract void setMarginPercent(YogaEdge edge, float percent); + + public abstract void setMarginAuto(YogaEdge edge); + + public abstract YogaValue getPadding(YogaEdge edge); + + public abstract void setPadding(YogaEdge edge, float padding); + + public abstract void setPaddingPercent(YogaEdge edge, float percent); + + public abstract float getBorder(YogaEdge edge); + + public abstract void setBorder(YogaEdge edge, float border); + + public abstract YogaValue getPosition(YogaEdge edge); + + public abstract void setPosition(YogaEdge edge, float position); + + public abstract void setPositionPercent(YogaEdge edge, float percent); + + public abstract YogaValue getWidth(); + + public abstract void setWidth(float width); + + public abstract void setWidthPercent(float percent); + + public abstract void setWidthAuto(); + + public abstract YogaValue getHeight(); + + public abstract void setHeight(float height); + + public abstract void setHeightPercent(float percent); + + public abstract void setHeightAuto(); + + public abstract YogaValue getMinWidth(); + + public abstract void setMinWidth(float minWidth); + + public abstract void setMinWidthPercent(float percent); + + public abstract YogaValue getMinHeight(); + + public abstract void setMinHeight(float minHeight); + + public abstract void setMinHeightPercent(float percent); + + public abstract YogaValue getMaxWidth(); + + public abstract void setMaxWidth(float maxWidth); + + public abstract void setMaxWidthPercent(float percent); + + public abstract YogaValue getMaxHeight(); + + public abstract void setMaxHeight(float maxheight); + + public abstract void setMaxHeightPercent(float percent); + + public abstract float getAspectRatio(); + + public abstract void setAspectRatio(float aspectRatio); + + public abstract float getLayoutX(); + + public abstract float getLayoutY(); + + public abstract float getLayoutWidth(); + + public abstract float getLayoutHeight(); + + public abstract float getLayoutMargin(YogaEdge edge); + + public abstract float getLayoutPadding(YogaEdge edge); + + public abstract float getLayoutBorder(YogaEdge edge); + + public abstract YogaDirection getLayoutDirection(); + + public abstract void setMeasureFunction(YogaMeasureFunction measureFunction); + + public abstract void setBaselineFunction(YogaBaselineFunction baselineFunction); + + public abstract boolean isMeasureDefined(); + + public abstract void setData(Object data); + + public abstract Object getData(); + + public abstract void print(); } diff --git a/java/com/facebook/yoga/YogaNodeJNI.java b/java/com/facebook/yoga/YogaNodeJNI.java new file mode 100644 index 00000000..9589a31b --- /dev/null +++ b/java/com/facebook/yoga/YogaNodeJNI.java @@ -0,0 +1,800 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + */ +package com.facebook.yoga; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.soloader.SoLoader; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; + +@DoNotStrip +public class YogaNodeJNI extends YogaNode implements Cloneable { + + static { + SoLoader.loadLibrary("yoga"); + } + + /** + * Get native instance count. Useful for testing only. + */ + static native int jni_YGNodeGetInstanceCount(); + + private YogaNodeJNI mOwner; + @Nullable private List mChildren; + private YogaMeasureFunction mMeasureFunction; + private YogaBaselineFunction mBaselineFunction; + private long mNativePointer; + private Object mData; + + /* Those flags needs be in sync with YGJNI.cpp */ + private static final int MARGIN = 1; + private static final int PADDING = 2; + private static final int BORDER = 4; + + @DoNotStrip + private int mEdgeSetFlag = 0; + + private boolean mHasSetPosition = false; + + @DoNotStrip + private float mWidth = YogaConstants.UNDEFINED; + @DoNotStrip + private float mHeight = YogaConstants.UNDEFINED; + @DoNotStrip + private float mTop = YogaConstants.UNDEFINED; + @DoNotStrip + private float mLeft = YogaConstants.UNDEFINED; + @DoNotStrip + private float mMarginLeft = 0; + @DoNotStrip + private float mMarginTop = 0; + @DoNotStrip + private float mMarginRight = 0; + @DoNotStrip + private float mMarginBottom = 0; + @DoNotStrip + private float mPaddingLeft = 0; + @DoNotStrip + private float mPaddingTop = 0; + @DoNotStrip + private float mPaddingRight = 0; + @DoNotStrip + private float mPaddingBottom = 0; + @DoNotStrip + private float mBorderLeft = 0; + @DoNotStrip + private float mBorderTop = 0; + @DoNotStrip + private float mBorderRight = 0; + @DoNotStrip + private float mBorderBottom = 0; + @DoNotStrip + private int mLayoutDirection = 0; + @DoNotStrip + private boolean mHasNewLayout = true; + @DoNotStrip private boolean mDoesLegacyStretchFlagAffectsLayout = false; + + private native long jni_YGNodeNew(); + public YogaNodeJNI() { + mNativePointer = jni_YGNodeNew(); + if (mNativePointer == 0) { + throw new IllegalStateException("Failed to allocate native memory"); + } + } + + private native long jni_YGNodeNewWithConfig(long configPointer); + public YogaNodeJNI(YogaConfig config) { + mNativePointer = jni_YGNodeNewWithConfig(config.mNativePointer); + if (mNativePointer == 0) { + throw new IllegalStateException("Failed to allocate native memory"); + } + } + + @Override + protected void finalize() throws Throwable { + try { + freeNatives(); + } finally { + super.finalize(); + } + } + + private static native void jni_YGNodeFree(long nativePointer); + + /* frees the native underlying YGNode. Useful for testing. */ + public void freeNatives() { + if (mNativePointer > 0) { + long nativePointer = mNativePointer; + mNativePointer = 0; + jni_YGNodeFree(nativePointer); + } + } + + private static native void jni_YGNodeReset(long nativePointer); + public void reset() { + mEdgeSetFlag = 0; + mHasSetPosition = false; + mHasNewLayout = true; + + mWidth = YogaConstants.UNDEFINED; + mHeight = YogaConstants.UNDEFINED; + mTop = YogaConstants.UNDEFINED; + mLeft = YogaConstants.UNDEFINED; + mMarginLeft = 0; + mMarginTop = 0; + mMarginRight = 0; + mMarginBottom = 0; + mPaddingLeft = 0; + mPaddingTop = 0; + mPaddingRight = 0; + mPaddingBottom = 0; + mBorderLeft = 0; + mBorderTop = 0; + mBorderRight = 0; + mBorderBottom = 0; + mLayoutDirection = 0; + + mMeasureFunction = null; + mBaselineFunction = null; + mData = null; + mDoesLegacyStretchFlagAffectsLayout = false; + + jni_YGNodeReset(mNativePointer); + } + + public int getChildCount() { + return mChildren == null ? 0 : mChildren.size(); + } + + public YogaNodeJNI getChildAt(int i) { + if (mChildren == null) { + throw new IllegalStateException("YogaNode does not have children"); + } + return mChildren.get(i); + } + + private static native void jni_YGNodeInsertChild(long nativePointer, long childPointer, int index); + + public void addChildAt(YogaNode c, int i) { + YogaNodeJNI child = (YogaNodeJNI) c; + if (child.mOwner != null) { + throw new IllegalStateException("Child already has a parent, it must be removed first."); + } + + if (mChildren == null) { + mChildren = new ArrayList<>(4); + } + mChildren.add(i, child); + child.mOwner = this; + jni_YGNodeInsertChild(mNativePointer, child.mNativePointer, i); + } + + private static native void jni_YGNodeSetIsReferenceBaseline(long nativePointer, boolean isReferenceBaseline); + + public void setIsReferenceBaseline(boolean isReferenceBaseline) { + jni_YGNodeSetIsReferenceBaseline(mNativePointer, isReferenceBaseline); + } + + private static native boolean jni_YGNodeIsReferenceBaseline(long nativePointer); + + public boolean isReferenceBaseline() { + return jni_YGNodeIsReferenceBaseline(mNativePointer); + } + + private static native void jni_YGNodeSetOwner(long nativePointer, long newOwnerNativePointer); + + private native long jni_YGNodeClone(long nativePointer, Object newNode); + + @Override + public YogaNodeJNI clone() { + try { + YogaNodeJNI clonedYogaNode = (YogaNodeJNI) super.clone(); + long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode); + + if (mChildren != null) { + for (YogaNodeJNI child : mChildren) { + jni_YGNodeSetOwner(child.mNativePointer, 0); + child.mOwner = null; + } + } + + clonedYogaNode.mNativePointer = clonedNativePointer; + clonedYogaNode.mOwner = null; + clonedYogaNode.mChildren = + mChildren != null ? (List) ((ArrayList) mChildren).clone() : null; + if (clonedYogaNode.mChildren != null) { + for (YogaNodeJNI child : clonedYogaNode.mChildren) { + child.mOwner = null; + } + } + return clonedYogaNode; + } catch (CloneNotSupportedException ex) { + // This class implements Cloneable, this should not happen + throw new RuntimeException(ex); + } + } + + public YogaNodeJNI cloneWithNewChildren() { + try { + YogaNodeJNI clonedYogaNode = (YogaNodeJNI) super.clone(); + long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode); + clonedYogaNode.mOwner = null; + clonedYogaNode.mNativePointer = clonedNativePointer; + clonedYogaNode.clearChildren(); + return clonedYogaNode; + } catch (CloneNotSupportedException ex) { + // This class implements Cloneable, this should not happen + throw new RuntimeException(ex); + } + } + + private static native void jni_YGNodeClearChildren(long nativePointer); + + private void clearChildren() { + mChildren = null; + jni_YGNodeClearChildren(mNativePointer); + } + + private static native void jni_YGNodeRemoveChild(long nativePointer, long childPointer); + public YogaNodeJNI removeChildAt(int i) { + if (mChildren == null) { + throw new IllegalStateException( + "Trying to remove a child of a YogaNode that does not have children"); + } + final YogaNodeJNI child = mChildren.remove(i); + child.mOwner = null; + jni_YGNodeRemoveChild(mNativePointer, child.mNativePointer); + return child; + } + + /** + * @returns the {@link YogaNode} that owns this {@link YogaNode}. + * The owner is used to identify the YogaTree that a {@link YogaNode} belongs + * to. + * This method will return the parent of the {@link YogaNode} when the + * {@link YogaNode} only belongs to one YogaTree or null when the + * {@link YogaNode} is shared between two or more YogaTrees. + */ + @Nullable + public YogaNodeJNI getOwner() { + return mOwner; + } + + /** @deprecated Use #getOwner() instead. This will be removed in the next version. */ + @Deprecated + @Nullable + public YogaNodeJNI getParent() { + return getOwner(); + } + + public int indexOf(YogaNode child) { + return mChildren == null ? -1 : mChildren.indexOf(child); + } + + private static native void jni_YGNodeCalculateLayout(long nativePointer, float width, float height); + public void calculateLayout(float width, float height) { + jni_YGNodeCalculateLayout(mNativePointer, width, height); + } + + public boolean hasNewLayout() { + return mHasNewLayout; + } + + private static native void jni_YGNodeMarkDirty(long nativePointer); + public void dirty() { + jni_YGNodeMarkDirty(mNativePointer); + } + + private static native void jni_YGNodeMarkDirtyAndPropogateToDescendants(long nativePointer); + + public void dirtyAllDescendants() { + jni_YGNodeMarkDirtyAndPropogateToDescendants(mNativePointer); + } + + private static native boolean jni_YGNodeIsDirty(long nativePointer); + public boolean isDirty() { + return jni_YGNodeIsDirty(mNativePointer); + } + + private static native void jni_YGNodeCopyStyle(long dstNativePointer, long srcNativePointer); + @Override + public void copyStyle(YogaNode srcNode) { + jni_YGNodeCopyStyle(mNativePointer, ((YogaNodeJNI) srcNode).mNativePointer); + } + + public void markLayoutSeen() { + mHasNewLayout = false; + } + + private static native int jni_YGNodeStyleGetDirection(long nativePointer); + public YogaDirection getStyleDirection() { + return YogaDirection.fromInt(jni_YGNodeStyleGetDirection(mNativePointer)); + } + + private static native void jni_YGNodeStyleSetDirection(long nativePointer, int direction); + public void setDirection(YogaDirection direction) { + jni_YGNodeStyleSetDirection(mNativePointer, direction.intValue()); + } + + private static native int jni_YGNodeStyleGetFlexDirection(long nativePointer); + public YogaFlexDirection getFlexDirection() { + return YogaFlexDirection.fromInt(jni_YGNodeStyleGetFlexDirection(mNativePointer)); + } + + private static native void jni_YGNodeStyleSetFlexDirection(long nativePointer, int flexDirection); + public void setFlexDirection(YogaFlexDirection flexDirection) { + jni_YGNodeStyleSetFlexDirection(mNativePointer, flexDirection.intValue()); + } + + private static native int jni_YGNodeStyleGetJustifyContent(long nativePointer); + public YogaJustify getJustifyContent() { + return YogaJustify.fromInt(jni_YGNodeStyleGetJustifyContent(mNativePointer)); + } + + private static native void jni_YGNodeStyleSetJustifyContent(long nativePointer, int justifyContent); + public void setJustifyContent(YogaJustify justifyContent) { + jni_YGNodeStyleSetJustifyContent(mNativePointer, justifyContent.intValue()); + } + + private static native int jni_YGNodeStyleGetAlignItems(long nativePointer); + public YogaAlign getAlignItems() { + return YogaAlign.fromInt(jni_YGNodeStyleGetAlignItems(mNativePointer)); + } + + private static native void jni_YGNodeStyleSetAlignItems(long nativePointer, int alignItems); + public void setAlignItems(YogaAlign alignItems) { + jni_YGNodeStyleSetAlignItems(mNativePointer, alignItems.intValue()); + } + + private static native int jni_YGNodeStyleGetAlignSelf(long nativePointer); + public YogaAlign getAlignSelf() { + return YogaAlign.fromInt(jni_YGNodeStyleGetAlignSelf(mNativePointer)); + } + + private static native void jni_YGNodeStyleSetAlignSelf(long nativePointer, int alignSelf); + public void setAlignSelf(YogaAlign alignSelf) { + jni_YGNodeStyleSetAlignSelf(mNativePointer, alignSelf.intValue()); + } + + private static native int jni_YGNodeStyleGetAlignContent(long nativePointer); + public YogaAlign getAlignContent() { + return YogaAlign.fromInt(jni_YGNodeStyleGetAlignContent(mNativePointer)); + } + + private static native void jni_YGNodeStyleSetAlignContent(long nativePointer, int alignContent); + public void setAlignContent(YogaAlign alignContent) { + jni_YGNodeStyleSetAlignContent(mNativePointer, alignContent.intValue()); + } + + private static native int jni_YGNodeStyleGetPositionType(long nativePointer); + public YogaPositionType getPositionType() { + return YogaPositionType.fromInt(jni_YGNodeStyleGetPositionType(mNativePointer)); + } + + private static native void jni_YGNodeStyleSetPositionType(long nativePointer, int positionType); + public void setPositionType(YogaPositionType positionType) { + jni_YGNodeStyleSetPositionType(mNativePointer, positionType.intValue()); + } + + private static native void jni_YGNodeStyleSetFlexWrap(long nativePointer, int wrapType); + public void setWrap(YogaWrap flexWrap) { + jni_YGNodeStyleSetFlexWrap(mNativePointer, flexWrap.intValue()); + } + + private static native int jni_YGNodeStyleGetOverflow(long nativePointer); + public YogaOverflow getOverflow() { + return YogaOverflow.fromInt(jni_YGNodeStyleGetOverflow(mNativePointer)); + } + + private static native void jni_YGNodeStyleSetOverflow(long nativePointer, int overflow); + public void setOverflow(YogaOverflow overflow) { + jni_YGNodeStyleSetOverflow(mNativePointer, overflow.intValue()); + } + + private static native int jni_YGNodeStyleGetDisplay(long nativePointer); + public YogaDisplay getDisplay() { + return YogaDisplay.fromInt(jni_YGNodeStyleGetDisplay(mNativePointer)); + } + + private static native void jni_YGNodeStyleSetDisplay(long nativePointer, int display); + public void setDisplay(YogaDisplay display) { + jni_YGNodeStyleSetDisplay(mNativePointer, display.intValue()); + } + + private static native void jni_YGNodeStyleSetFlex(long nativePointer, float flex); + public void setFlex(float flex) { + jni_YGNodeStyleSetFlex(mNativePointer, flex); + } + + private static native float jni_YGNodeStyleGetFlexGrow(long nativePointer); + public float getFlexGrow() { + return jni_YGNodeStyleGetFlexGrow(mNativePointer); + } + + private static native void jni_YGNodeStyleSetFlexGrow(long nativePointer, float flexGrow); + public void setFlexGrow(float flexGrow) { + jni_YGNodeStyleSetFlexGrow(mNativePointer, flexGrow); + } + + private static native float jni_YGNodeStyleGetFlexShrink(long nativePointer); + public float getFlexShrink() { + return jni_YGNodeStyleGetFlexShrink(mNativePointer); + } + + private static native void jni_YGNodeStyleSetFlexShrink(long nativePointer, float flexShrink); + public void setFlexShrink(float flexShrink) { + jni_YGNodeStyleSetFlexShrink(mNativePointer, flexShrink); + } + + private static native Object jni_YGNodeStyleGetFlexBasis(long nativePointer); + public YogaValue getFlexBasis() { + return (YogaValue) jni_YGNodeStyleGetFlexBasis(mNativePointer); + } + + private static native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis); + public void setFlexBasis(float flexBasis) { + jni_YGNodeStyleSetFlexBasis(mNativePointer, flexBasis); + } + + private static native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent); + public void setFlexBasisPercent(float percent) { + jni_YGNodeStyleSetFlexBasisPercent(mNativePointer, percent); + } + + private static native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer); + public void setFlexBasisAuto() { + jni_YGNodeStyleSetFlexBasisAuto(mNativePointer); + } + + private static native Object jni_YGNodeStyleGetMargin(long nativePointer, int edge); + public YogaValue getMargin(YogaEdge edge) { + if (!((mEdgeSetFlag & MARGIN) == MARGIN)) { + return YogaValue.UNDEFINED; + } + return (YogaValue) jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()); + } + + private static native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin); + public void setMargin(YogaEdge edge, float margin) { + mEdgeSetFlag |= MARGIN; + jni_YGNodeStyleSetMargin(mNativePointer, edge.intValue(), margin); + } + + private static native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent); + public void setMarginPercent(YogaEdge edge, float percent) { + mEdgeSetFlag |= MARGIN; + jni_YGNodeStyleSetMarginPercent(mNativePointer, edge.intValue(), percent); + } + + private static native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge); + public void setMarginAuto(YogaEdge edge) { + mEdgeSetFlag |= MARGIN; + jni_YGNodeStyleSetMarginAuto(mNativePointer, edge.intValue()); + } + + private static native Object jni_YGNodeStyleGetPadding(long nativePointer, int edge); + public YogaValue getPadding(YogaEdge edge) { + if (!((mEdgeSetFlag & PADDING) == PADDING)) { + return YogaValue.UNDEFINED; + } + return (YogaValue) jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()); + } + + private static native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding); + public void setPadding(YogaEdge edge, float padding) { + mEdgeSetFlag |= PADDING; + jni_YGNodeStyleSetPadding(mNativePointer, edge.intValue(), padding); + } + + private static native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent); + public void setPaddingPercent(YogaEdge edge, float percent) { + mEdgeSetFlag |= PADDING; + jni_YGNodeStyleSetPaddingPercent(mNativePointer, edge.intValue(), percent); + } + + private static native float jni_YGNodeStyleGetBorder(long nativePointer, int edge); + public float getBorder(YogaEdge edge) { + if (!((mEdgeSetFlag & BORDER) == BORDER)) { + return YogaConstants.UNDEFINED; + } + return jni_YGNodeStyleGetBorder(mNativePointer, edge.intValue()); + } + + private static native void jni_YGNodeStyleSetBorder(long nativePointer, int edge, float border); + public void setBorder(YogaEdge edge, float border) { + mEdgeSetFlag |= BORDER; + jni_YGNodeStyleSetBorder(mNativePointer, edge.intValue(), border); + } + + private static native Object jni_YGNodeStyleGetPosition(long nativePointer, int edge); + public YogaValue getPosition(YogaEdge edge) { + if (!mHasSetPosition) { + return YogaValue.UNDEFINED; + } + return (YogaValue) jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()); + } + + private static native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position); + public void setPosition(YogaEdge edge, float position) { + mHasSetPosition = true; + jni_YGNodeStyleSetPosition(mNativePointer, edge.intValue(), position); + } + + private static native void jni_YGNodeStyleSetPositionPercent(long nativePointer, int edge, float percent); + public void setPositionPercent(YogaEdge edge, float percent) { + mHasSetPosition = true; + jni_YGNodeStyleSetPositionPercent(mNativePointer, edge.intValue(), percent); + } + + private static native Object jni_YGNodeStyleGetWidth(long nativePointer); + public YogaValue getWidth() { + return (YogaValue) jni_YGNodeStyleGetWidth(mNativePointer); + } + + private static native void jni_YGNodeStyleSetWidth(long nativePointer, float width); + public void setWidth(float width) { + jni_YGNodeStyleSetWidth(mNativePointer, width); + } + + private static native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent); + public void setWidthPercent(float percent) { + jni_YGNodeStyleSetWidthPercent(mNativePointer, percent); + } + + private static native void jni_YGNodeStyleSetWidthAuto(long nativePointer); + public void setWidthAuto() { + jni_YGNodeStyleSetWidthAuto(mNativePointer); + } + + private static native Object jni_YGNodeStyleGetHeight(long nativePointer); + public YogaValue getHeight() { + return (YogaValue) jni_YGNodeStyleGetHeight(mNativePointer); + } + + private static native void jni_YGNodeStyleSetHeight(long nativePointer, float height); + public void setHeight(float height) { + jni_YGNodeStyleSetHeight(mNativePointer, height); + } + + private static native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent); + public void setHeightPercent(float percent) { + jni_YGNodeStyleSetHeightPercent(mNativePointer, percent); + } + + private static native void jni_YGNodeStyleSetHeightAuto(long nativePointer); + public void setHeightAuto() { + jni_YGNodeStyleSetHeightAuto(mNativePointer); + } + + private static native Object jni_YGNodeStyleGetMinWidth(long nativePointer); + public YogaValue getMinWidth() { + return (YogaValue) jni_YGNodeStyleGetMinWidth(mNativePointer); + } + + private static native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth); + public void setMinWidth(float minWidth) { + jni_YGNodeStyleSetMinWidth(mNativePointer, minWidth); + } + + private static native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent); + public void setMinWidthPercent(float percent) { + jni_YGNodeStyleSetMinWidthPercent(mNativePointer, percent); + } + + private static native Object jni_YGNodeStyleGetMinHeight(long nativePointer); + public YogaValue getMinHeight() { + return (YogaValue) jni_YGNodeStyleGetMinHeight(mNativePointer); + } + + private static native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight); + public void setMinHeight(float minHeight) { + jni_YGNodeStyleSetMinHeight(mNativePointer, minHeight); + } + + private static native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent); + public void setMinHeightPercent(float percent) { + jni_YGNodeStyleSetMinHeightPercent(mNativePointer, percent); + } + + private static native Object jni_YGNodeStyleGetMaxWidth(long nativePointer); + public YogaValue getMaxWidth() { + return (YogaValue) jni_YGNodeStyleGetMaxWidth(mNativePointer); + } + + private static native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth); + public void setMaxWidth(float maxWidth) { + jni_YGNodeStyleSetMaxWidth(mNativePointer, maxWidth); + } + + private static native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent); + public void setMaxWidthPercent(float percent) { + jni_YGNodeStyleSetMaxWidthPercent(mNativePointer, percent); + } + + private static native Object jni_YGNodeStyleGetMaxHeight(long nativePointer); + public YogaValue getMaxHeight() { + return (YogaValue) jni_YGNodeStyleGetMaxHeight(mNativePointer); + } + + private static native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight); + public void setMaxHeight(float maxheight) { + jni_YGNodeStyleSetMaxHeight(mNativePointer, maxheight); + } + + private static native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent); + public void setMaxHeightPercent(float percent) { + jni_YGNodeStyleSetMaxHeightPercent(mNativePointer, percent); + } + + private static native float jni_YGNodeStyleGetAspectRatio(long nativePointer); + public float getAspectRatio() { + return jni_YGNodeStyleGetAspectRatio(mNativePointer); + } + + private static native void jni_YGNodeStyleSetAspectRatio(long nativePointer, float aspectRatio); + public void setAspectRatio(float aspectRatio) { + jni_YGNodeStyleSetAspectRatio(mNativePointer, aspectRatio); + } + + public float getLayoutX() { + return mLeft; + } + + public float getLayoutY() { + return mTop; + } + + public float getLayoutWidth() { + return mWidth; + } + + public float getLayoutHeight() { + return mHeight; + } + + public boolean getDoesLegacyStretchFlagAffectsLayout() { + return mDoesLegacyStretchFlagAffectsLayout; + } + + public float getLayoutMargin(YogaEdge edge) { + switch (edge) { + case LEFT: + return mMarginLeft; + case TOP: + return mMarginTop; + case RIGHT: + return mMarginRight; + case BOTTOM: + return mMarginBottom; + case START: + return getLayoutDirection() == YogaDirection.RTL ? mMarginRight : mMarginLeft; + case END: + return getLayoutDirection() == YogaDirection.RTL ? mMarginLeft : mMarginRight; + default: + throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands"); + } + } + + public float getLayoutPadding(YogaEdge edge) { + switch (edge) { + case LEFT: + return mPaddingLeft; + case TOP: + return mPaddingTop; + case RIGHT: + return mPaddingRight; + case BOTTOM: + return mPaddingBottom; + case START: + return getLayoutDirection() == YogaDirection.RTL ? mPaddingRight : mPaddingLeft; + case END: + return getLayoutDirection() == YogaDirection.RTL ? mPaddingLeft : mPaddingRight; + default: + throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands"); + } + } + + public float getLayoutBorder(YogaEdge edge) { + switch (edge) { + case LEFT: + return mBorderLeft; + case TOP: + return mBorderTop; + case RIGHT: + return mBorderRight; + case BOTTOM: + return mBorderBottom; + case START: + return getLayoutDirection() == YogaDirection.RTL ? mBorderRight : mBorderLeft; + case END: + return getLayoutDirection() == YogaDirection.RTL ? mBorderLeft : mBorderRight; + default: + throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands"); + } + } + + public YogaDirection getLayoutDirection() { + return YogaDirection.fromInt(mLayoutDirection); + } + + private static native void jni_YGNodeSetHasMeasureFunc(long nativePointer, boolean hasMeasureFunc); + public void setMeasureFunction(YogaMeasureFunction measureFunction) { + mMeasureFunction = measureFunction; + jni_YGNodeSetHasMeasureFunc(mNativePointer, measureFunction != null); + } + + // Implementation Note: Why this method needs to stay final + // + // We cache the jmethodid for this method in Yoga code. This means that even if a subclass + // were to override measure, we'd still call this implementation from layout code since the + // overriding method will have a different jmethodid. This is final to prevent that mistake. + @DoNotStrip + public final long measure(float width, int widthMode, float height, int heightMode) { + if (!isMeasureDefined()) { + throw new RuntimeException("Measure function isn't defined!"); + } + + return mMeasureFunction.measure( + this, + width, + YogaMeasureMode.fromInt(widthMode), + height, + YogaMeasureMode.fromInt(heightMode)); + } + + private static native void jni_YGNodeSetHasBaselineFunc(long nativePointer, boolean hasMeasureFunc); + public void setBaselineFunction(YogaBaselineFunction baselineFunction) { + mBaselineFunction = baselineFunction; + jni_YGNodeSetHasBaselineFunc(mNativePointer, baselineFunction != null); + } + + @DoNotStrip + public final float baseline(float width, float height) { + return mBaselineFunction.baseline(this, width, height); + } + + public boolean isMeasureDefined() { + return mMeasureFunction != null; + } + + public void setData(Object data) { + mData = data; + } + + public Object getData() { + return mData; + } + + private static native void jni_YGNodePrint(long nativePointer); + + /** + * Use the set logger (defaults to adb log) to print out the styles, children, and computed + * layout of the tree rooted at this node. + */ + public void print() { + jni_YGNodePrint(mNativePointer); + } + + /** + * This method replaces the child at childIndex position with the newNode received by parameter. + * This is different than calling removeChildAt and addChildAt because this method ONLY replaces + * the child in the mChildren datastructure. @DoNotStrip: called from JNI + * + * @return the nativePointer of the newNode {@linl YogaNode} + */ + @DoNotStrip + private final long replaceChild(YogaNodeJNI newNode, int childIndex) { + if (mChildren == null) { + throw new IllegalStateException("Cannot replace child. YogaNode does not have children"); + } + mChildren.remove(childIndex); + mChildren.add(childIndex, newNode); + newNode.mOwner = this; + return newNode.mNativePointer; + } +} diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 8d0773a2..2bfac9bf 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -15,7 +15,7 @@ using namespace std; using facebook::yoga::detail::Log; struct JYogaNode : public JavaClass { - static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaNode;"; + static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaNodeJNI;"; }; struct JYogaConfig : public JavaClass { @@ -98,7 +98,7 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { static auto doesLegacyStretchBehaviour = obj->getClass()->getField( "mDoesLegacyStretchFlagAffectsLayout"); - /* Those flags needs be in sync with YogaNode.java */ + /* Those flags needs be in sync with YogaNodeJNI.java */ const int MARGIN = 1; const int PADDING = 2; const int BORDER = 4; @@ -168,7 +168,7 @@ static void YGPrint(YGNodeRef node) { static float YGJNIBaselineFunc(YGNodeRef node, float width, float height) { if (auto obj = YGNodeJobject(node)->lockLocal()) { static auto baselineFunc = - findClassStatic("com/facebook/yoga/YogaNode") + findClassStatic("com/facebook/yoga/YogaNodeJNI") ->getMethod("baseline"); return baselineFunc(obj, width, height); } else { @@ -208,7 +208,7 @@ static YGNodeRef YGJNIOnNodeClonedFunc( childIndex); static auto replaceChild = - findClassStatic("com/facebook/yoga/YogaNode") + findClassStatic("com/facebook/yoga/YogaNodeJNI") ->getMethod, jint)>("replaceChild"); jlong newNodeNativePointer = @@ -225,7 +225,7 @@ static YGSize YGJNIMeasureFunc( YGMeasureMode heightMode) { if (auto obj = YGNodeJobject(node)->lockLocal()) { static auto measureFunc = - findClassStatic("com/facebook/yoga/YogaNode") + findClassStatic("com/facebook/yoga/YogaNodeJNI") ->getMethod("measure"); YGTransferLayoutDirection(node, obj); @@ -661,7 +661,7 @@ jint jni_YGNodeGetInstanceCount() { jint JNI_OnLoad(JavaVM* vm, void*) { return initialize(vm, [] { registerNatives( - "com/facebook/yoga/YogaNode", + "com/facebook/yoga/YogaNodeJNI", { YGMakeNativeMethod(jni_YGNodeNew), YGMakeNativeMethod(jni_YGNodeNewWithConfig), diff --git a/java/tests/com/facebook/yoga/YogaNodeTest.java b/java/tests/com/facebook/yoga/YogaNodeTest.java index 4b8a2ce5..dad8ee62 100644 --- a/java/tests/com/facebook/yoga/YogaNodeTest.java +++ b/java/tests/com/facebook/yoga/YogaNodeTest.java @@ -30,9 +30,9 @@ public class YogaNodeTest { @Test public void testInit() { - final int refCount = YogaNode.jni_YGNodeGetInstanceCount(); + final int refCount = YogaNodeJNI.jni_YGNodeGetInstanceCount(); final YogaNode node = createNode(); - assertEquals(refCount + 1, YogaNode.jni_YGNodeGetInstanceCount()); + assertEquals(refCount + 1, YogaNodeJNI.jni_YGNodeGetInstanceCount()); } @Test @@ -243,7 +243,7 @@ public class YogaNodeTest { child.addChildAt(grandChild, 0); child.setFlexDirection(YogaFlexDirection.ROW); - YogaNode clonedChild = child.clone(); + YogaNode clonedChild = ((YogaNodeJNI) child).clone(); assertNotSame(clonedChild, child); @@ -270,7 +270,7 @@ public class YogaNodeTest { child.addChildAt(grandChild, 0); child.setFlexDirection(YogaFlexDirection.ROW); - YogaNode clonedChild = child.cloneWithNewChildren(); + YogaNode clonedChild = ((YogaNodeJNI) child).cloneWithNewChildren(); assertNotSame(clonedChild, child); assertEquals(YogaFlexDirection.ROW, clonedChild.getFlexDirection()); @@ -288,7 +288,7 @@ public class YogaNodeTest { @Override public YogaNode cloneNode(YogaNode oldNode, YogaNode owner, int childIndex) { onNodeClonedExecuted.set(true); - return oldNode.clone(); + return ((YogaNodeJNI) oldNode).clone(); } }); YogaNode root = createNode(config); @@ -300,7 +300,7 @@ public class YogaNodeTest { root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); // Force a clone to happen. - final YogaNode root2 = root.clone(); + final YogaNode root2 = ((YogaNodeJNI) root).clone(); root2.setWidth(200f); root2.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); @@ -319,7 +319,7 @@ public class YogaNodeTest { new YogaNodeCloneFunction() { @Override public YogaNode cloneNode(YogaNode oldNode, YogaNode owner, int childIndex) { - return oldNode.clone(); + return ((YogaNodeJNI) oldNode).clone(); } }); config.setOnCloneNode(null); @@ -359,7 +359,7 @@ public class YogaNodeTest { root_child0_child0_child0.setFlexShrink(1); root_child0_child0.addChildAt(root_child0_child0_child0, 0); root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); - assertFalse(root.getDoesLegacyStretchFlagAffectsLayout()); + assertFalse(((YogaNodeJNI) root).getDoesLegacyStretchFlagAffectsLayout()); } @Test