From e983c4a5ef32edfcda36b8197701196a56e610d5 Mon Sep 17 00:00:00 2001 From: Pasquale Anatriello Date: Thu, 30 Jan 2020 03:41:45 -0800 Subject: [PATCH] Swap child Yoga Summary: Changelog: [Internal] Expose the replaceChild Yoga call to Java Reviewed By: SidharthGuglani Differential Revision: D19497193 fbshipit-source-id: 153243cc1d8c23dcaf2c772ca794bd59a230f652 --- java/com/facebook/yoga/YogaNative.java | 1 + java/com/facebook/yoga/YogaNode.java | 2 + java/com/facebook/yoga/YogaNodeJNIBase.java | 87 +++++++++++++++------ java/jni/YGJNIVanilla.cpp | 11 +++ yoga/Yoga.cpp | 8 ++ yoga/Yoga.h | 5 ++ 6 files changed, 92 insertions(+), 22 deletions(-) diff --git a/java/com/facebook/yoga/YogaNative.java b/java/com/facebook/yoga/YogaNative.java index 334eaab5..3674b42f 100644 --- a/java/com/facebook/yoga/YogaNative.java +++ b/java/com/facebook/yoga/YogaNative.java @@ -34,6 +34,7 @@ public class YogaNative { static native void jni_YGNodeFreeJNI(long nativePointer); static native void jni_YGNodeResetJNI(long nativePointer); static native void jni_YGNodeInsertChildJNI(long nativePointer, long childPointer, int index); + static native void jni_YGNodeSwapChildJNI(long nativePointer, long childPointer, int index); static native void jni_YGNodeSetIsReferenceBaselineJNI(long nativePointer, boolean isReferenceBaseline); static native boolean jni_YGNodeIsReferenceBaselineJNI(long nativePointer); static native void jni_YGNodeClearChildrenJNI(long nativePointer); diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index baa0c517..9fc8bac9 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -214,4 +214,6 @@ public abstract class YogaNode { public abstract void print(); public abstract YogaNode cloneWithoutChildren(); + + public abstract YogaNode cloneWithChildren(); } diff --git a/java/com/facebook/yoga/YogaNodeJNIBase.java b/java/com/facebook/yoga/YogaNodeJNIBase.java index 6372ddd7..e20a5389 100644 --- a/java/com/facebook/yoga/YogaNodeJNIBase.java +++ b/java/com/facebook/yoga/YogaNodeJNIBase.java @@ -39,11 +39,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { protected long mNativePointer; @Nullable private Object mData; - @DoNotStrip - private @Nullable float[] arr = null; + @DoNotStrip private @Nullable float[] arr = null; - @DoNotStrip - private int mLayoutDirection = 0; + @DoNotStrip private int mLayoutDirection = 0; private boolean mHasNewLayout = true; @@ -59,7 +57,7 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { } YogaNodeJNIBase(YogaConfig config) { - this(YogaNative.jni_YGNodeNewWithConfigJNI(((YogaConfigJNIBase)config).mNativePointer)); + this(YogaNative.jni_YGNodeNewWithConfigJNI(((YogaConfigJNIBase) config).mNativePointer)); } public void reset() { @@ -106,6 +104,32 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { return YogaNative.jni_YGNodeIsReferenceBaselineJNI(mNativePointer); } + public void swapChildAt(YogaNode newChild, int position) { + YogaNodeJNIBase child = (YogaNodeJNIBase) newChild; + mChildren.remove(position); + mChildren.add(position, child); + child.mOwner = this; + YogaNative.jni_YGNodeSwapChildJNI(mNativePointer, child.mNativePointer, position); + } + + @Override + public YogaNodeJNIBase cloneWithChildren() { + try { + YogaNodeJNIBase clonedYogaNode = (YogaNodeJNIBase) super.clone(); + long clonedNativePointer = YogaNative.jni_YGNodeCloneJNI(mNativePointer); + clonedYogaNode.mOwner = null; + clonedYogaNode.mNativePointer = clonedNativePointer; + for (int i = 0; i < clonedYogaNode.getChildCount(); i++) { + clonedYogaNode.swapChildAt(clonedYogaNode.getChildAt(i).cloneWithChildren(), i); + } + + return clonedYogaNode; + } catch (CloneNotSupportedException ex) { + // This class implements Cloneable, this should not happen + throw new RuntimeException(ex); + } + } + @Override public YogaNodeJNIBase cloneWithoutChildren() { try { @@ -138,10 +162,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { } /** - * 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. + * 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. * * @return the {@link YogaNode} that owns this {@link YogaNode}. */ @@ -168,7 +191,7 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { ArrayList n = new ArrayList<>(); n.add(this); for (int i = 0; i < n.size(); ++i) { - List children = n.get(i).mChildren; + List children = n.get(i).mChildren; if (children != null) { n.addAll(children); } @@ -509,8 +532,8 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { } /** - * Use the set logger (defaults to adb log) to print out the styles, children, and computed - * layout of the tree rooted at this node. + * 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() { YogaNative.jni_YGNodePrintJNI(mNativePointer); @@ -559,7 +582,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { } public boolean getDoesLegacyStretchFlagAffectsLayout() { - return arr != null && (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & DOES_LEGACY_STRETCH_BEHAVIOUR) == DOES_LEGACY_STRETCH_BEHAVIOUR); + return arr != null + && (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & DOES_LEGACY_STRETCH_BEHAVIOUR) + == DOES_LEGACY_STRETCH_BEHAVIOUR); } @Override @@ -575,9 +600,13 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { case BOTTOM: return arr[LAYOUT_MARGIN_START_INDEX + 3]; case START: - return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX + 2] : arr[LAYOUT_MARGIN_START_INDEX]; + return getLayoutDirection() == YogaDirection.RTL + ? arr[LAYOUT_MARGIN_START_INDEX + 2] + : arr[LAYOUT_MARGIN_START_INDEX]; case END: - return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX] : arr[LAYOUT_MARGIN_START_INDEX + 2]; + return getLayoutDirection() == YogaDirection.RTL + ? arr[LAYOUT_MARGIN_START_INDEX] + : arr[LAYOUT_MARGIN_START_INDEX + 2]; default: throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands"); } @@ -589,7 +618,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { @Override public float getLayoutPadding(YogaEdge edge) { if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) { - int paddingStartIndex = LAYOUT_PADDING_START_INDEX - ((((int)arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4); + int paddingStartIndex = + LAYOUT_PADDING_START_INDEX + - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4); switch (edge) { case LEFT: return arr[paddingStartIndex]; @@ -600,9 +631,13 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { case BOTTOM: return arr[paddingStartIndex + 3]; case START: - return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex + 2] : arr[paddingStartIndex]; + return getLayoutDirection() == YogaDirection.RTL + ? arr[paddingStartIndex + 2] + : arr[paddingStartIndex]; case END: - return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex] : arr[paddingStartIndex + 2]; + return getLayoutDirection() == YogaDirection.RTL + ? arr[paddingStartIndex] + : arr[paddingStartIndex + 2]; default: throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands"); } @@ -614,7 +649,10 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { @Override public float getLayoutBorder(YogaEdge edge) { if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & BORDER) == BORDER) { - int borderStartIndex = LAYOUT_BORDER_START_INDEX - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4) - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) ? 0 : 4); + int borderStartIndex = + LAYOUT_BORDER_START_INDEX + - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4) + - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) ? 0 : 4); switch (edge) { case LEFT: return arr[borderStartIndex]; @@ -625,9 +663,13 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { case BOTTOM: return arr[borderStartIndex + 3]; case START: - return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex + 2] : arr[borderStartIndex]; + return getLayoutDirection() == YogaDirection.RTL + ? arr[borderStartIndex + 2] + : arr[borderStartIndex]; case END: - return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex] : arr[borderStartIndex + 2]; + return getLayoutDirection() == YogaDirection.RTL + ? arr[borderStartIndex] + : arr[borderStartIndex + 2]; default: throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands"); } @@ -638,7 +680,8 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { @Override public YogaDirection getLayoutDirection() { - return YogaDirection.fromInt(arr != null ? (int) arr[LAYOUT_DIRECTION_INDEX] : mLayoutDirection); + return YogaDirection.fromInt( + arr != null ? (int) arr[LAYOUT_DIRECTION_INDEX] : mLayoutDirection); } @Override diff --git a/java/jni/YGJNIVanilla.cpp b/java/jni/YGJNIVanilla.cpp index b9b590ac..6e66c06e 100644 --- a/java/jni/YGJNIVanilla.cpp +++ b/java/jni/YGJNIVanilla.cpp @@ -225,6 +225,16 @@ static void jni_YGNodeInsertChildJNI( _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); } +static void jni_YGNodeSwapChildJNI( + JNIEnv* env, + jobject obj, + jlong nativePointer, + jlong childPointer, + jint index) { + YGNodeSwapChild( + _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); +} + static void jni_YGNodeSetIsReferenceBaselineJNI( JNIEnv* env, jobject obj, @@ -754,6 +764,7 @@ static JNINativeMethod methods[] = { {"jni_YGNodeFreeJNI", "(J)V", (void*) jni_YGNodeFreeJNI}, {"jni_YGNodeResetJNI", "(J)V", (void*) jni_YGNodeResetJNI}, {"jni_YGNodeInsertChildJNI", "(JJI)V", (void*) jni_YGNodeInsertChildJNI}, + {"jni_YGNodeSwapChildJNI", "(JJI)V", (void*) jni_YGNodeSwapChildJNI}, {"jni_YGNodeSetIsReferenceBaselineJNI", "(JZ)V", (void*) jni_YGNodeSetIsReferenceBaselineJNI}, diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 41de5119..e30a36b7 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -386,6 +386,14 @@ YOGA_EXPORT void YGNodeInsertChild( owner->markDirtyAndPropogate(); } +YOGA_EXPORT void YGNodeSwapChild( + const YGNodeRef owner, + const YGNodeRef child, + const uint32_t index) { + owner->replaceChild(child, index); + child->setOwner(owner); +} + YOGA_EXPORT void YGNodeRemoveChild( const YGNodeRef owner, const YGNodeRef excludedChild) { diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 68ed0a62..2fe60a41 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -69,6 +69,11 @@ WIN_EXPORT void YGNodeInsertChild( YGNodeRef child, uint32_t index); +WIN_EXPORT void YGNodeSwapChild( + YGNodeRef node, + YGNodeRef child, + uint32_t index); + WIN_EXPORT void YGNodeRemoveChild(YGNodeRef node, YGNodeRef child); WIN_EXPORT void YGNodeRemoveAllChildren(YGNodeRef node); WIN_EXPORT YGNodeRef YGNodeGetChild(YGNodeRef node, uint32_t index);