From 7a5bf02275a5ebf81da7d589f8e802bd5ec8cbf0 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Wed, 3 Apr 2024 08:03:10 -0700 Subject: [PATCH] Migrate Spacing.java to Kotlin (#43733) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43733 ## Changelog: [Internal] - As in the title. Reviewed By: tdn120 Differential Revision: D55574525 fbshipit-source-id: a39b376026729c56d59e61db1a7d4a01711836be --- .../ReactAndroid/api/ReactAndroid.api | 16 +- .../react/uimanager/ReactShadowNodeImpl.java | 2 +- .../com/facebook/react/uimanager/Spacing.java | 210 ------------------ .../com/facebook/react/uimanager/Spacing.kt | 203 +++++++++++++++++ 4 files changed, 215 insertions(+), 216 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.java create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.kt diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index c0d2ec9e7c9..bba39b5d0ec 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -4795,12 +4795,13 @@ public abstract class com/facebook/react/uimanager/SimpleViewManager : com/faceb public fun updateExtraData (Landroid/view/View;Ljava/lang/Object;)V } -public class com/facebook/react/uimanager/Spacing { +public final class com/facebook/react/uimanager/Spacing { public static final field ALL I public static final field BLOCK I public static final field BLOCK_END I public static final field BLOCK_START I public static final field BOTTOM I + public static final field Companion Lcom/facebook/react/uimanager/Spacing$Companion; public static final field END I public static final field HORIZONTAL I public static final field LEFT I @@ -4810,11 +4811,16 @@ public class com/facebook/react/uimanager/Spacing { public static final field VERTICAL I public fun ()V public fun (F)V + public fun (F[F)V public fun (Lcom/facebook/react/uimanager/Spacing;)V - public fun get (I)F - public fun getRaw (I)F - public fun reset ()V - public fun set (IF)Z + public final fun get (I)F + public final fun getRaw (I)F + public final fun getWithFallback (II)F + public final fun reset ()V + public final fun set (IF)Z +} + +public final class com/facebook/react/uimanager/Spacing$Companion { } public abstract interface class com/facebook/react/uimanager/StateWrapper { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java index c08b1c73b6b..2ac0e27b4d6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java @@ -89,7 +89,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode private Integer mHeightMeasureSpec; public ReactShadowNodeImpl() { - mDefaultPadding = new Spacing(0); + mDefaultPadding = new Spacing(0f); if (!isVirtual()) { YogaNode node = YogaNodePool.get().acquire(); mYogaNode = node == null ? YogaNodeFactory.create(sYogaConfig) : node; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.java deleted file mode 100644 index 95d4dd71cef..00000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and 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.react.uimanager; - -import com.facebook.infer.annotation.Nullsafe; -import com.facebook.yoga.YogaConstants; -import java.util.Arrays; - -/** - * Class representing CSS spacing (padding, margin, and borders). This is mostly necessary to - * properly implement interactions and updates for properties like margin, marginLeft, and - * marginHorizontal. - */ -@Nullsafe(Nullsafe.Mode.LOCAL) -public class Spacing { - - /** Spacing type that represents the left direction. E.g. {@code marginLeft}. */ - public static final int LEFT = 0; - - /** Spacing type that represents the top direction. E.g. {@code marginTop}. */ - public static final int TOP = 1; - - /** Spacing type that represents the right direction. E.g. {@code marginRight}. */ - public static final int RIGHT = 2; - - /** Spacing type that represents the bottom direction. E.g. {@code marginBottom}. */ - public static final int BOTTOM = 3; - - /** - * Spacing type that represents start direction e.g. left in left-to-right, right in - * right-to-left. - */ - public static final int START = 4; - - /** - * Spacing type that represents end direction e.g. right in left-to-right, left in right-to-left. - */ - public static final int END = 5; - - /** - * Spacing type that represents horizontal direction (left and right). E.g. {@code - * marginHorizontal}. - */ - public static final int HORIZONTAL = 6; - - /** - * Spacing type that represents vertical direction (top and bottom). E.g. {@code marginVertical}. - */ - public static final int VERTICAL = 7; - - /** - * Spacing type that represents all directions (left, top, right, bottom). E.g. {@code margin}. - */ - public static final int ALL = 8; - - /** Spacing type that represents block directions (top, bottom). E.g. {@code marginBlock}. */ - public static final int BLOCK = 9; - - /** Spacing type that represents the block end direction (bottom). E.g. {@code marginBlockEnd}. */ - public static final int BLOCK_END = 10; - - /** - * Spacing type that represents the block start direction (top). E.g. {@code marginBlockStart}. - */ - public static final int BLOCK_START = 11; - - private static final int[] sFlagsMap = { - 1, /*LEFT*/ 2, /*TOP*/ 4, /*RIGHT*/ 8, /*BOTTOM*/ 16, /*START*/ 32, /*END*/ 64, /*HORIZONTAL*/ - 128, /*VERTICAL*/ 256, /*ALL*/ 512, /*BLOCK*/ 1024, /*BLOCK_END*/ 2048, /*BLOCK_START*/ - }; - - private final float[] mSpacing; - private int mValueFlags = 0; - private final float mDefaultValue; - private boolean mHasAliasesSet; - - public Spacing() { - this(0); - } - - public Spacing(float defaultValue) { - mDefaultValue = defaultValue; - mSpacing = newFullSpacingArray(); - } - - public Spacing(Spacing original) { - mDefaultValue = original.mDefaultValue; - mSpacing = Arrays.copyOf(original.mSpacing, original.mSpacing.length); - mValueFlags = original.mValueFlags; - mHasAliasesSet = original.mHasAliasesSet; - } - - /** - * Set a spacing value. - * - * @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}, {@link - * #VERTICAL}, {@link #HORIZONTAL}, {@link #ALL} - * @param value the value for this direction - * @return {@code true} if the spacing has changed, or {@code false} if the same value was already - * set - */ - public boolean set(int spacingType, float value) { - if (!FloatUtil.floatsEqual(mSpacing[spacingType], value)) { - mSpacing[spacingType] = value; - - if (YogaConstants.isUndefined(value)) { - mValueFlags &= ~sFlagsMap[spacingType]; - } else { - mValueFlags |= sFlagsMap[spacingType]; - } - - mHasAliasesSet = - (mValueFlags & sFlagsMap[ALL]) != 0 - || (mValueFlags & sFlagsMap[VERTICAL]) != 0 - || (mValueFlags & sFlagsMap[HORIZONTAL]) != 0 - || (mValueFlags & sFlagsMap[BLOCK]) != 0; - - return true; - } - - return false; - } - - /** - * Get the spacing for a direction. This takes into account any default values that have been set. - * - * @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM} - */ - public float get(int spacingType) { - float defaultValue = - (spacingType == START - || spacingType == END - || spacingType == BLOCK - || spacingType == BLOCK_END - || spacingType == BLOCK_START - ? YogaConstants.UNDEFINED - : mDefaultValue); - - if (mValueFlags == 0) { - return defaultValue; - } - - if ((mValueFlags & sFlagsMap[spacingType]) != 0) { - return mSpacing[spacingType]; - } - - if (mHasAliasesSet) { - int secondType = spacingType == TOP || spacingType == BOTTOM ? VERTICAL : HORIZONTAL; - if ((mValueFlags & sFlagsMap[secondType]) != 0) { - return mSpacing[secondType]; - } else if ((mValueFlags & sFlagsMap[ALL]) != 0) { - return mSpacing[ALL]; - } - } - - return defaultValue; - } - - /** - * Get the raw value (that was set using {@link #set(int, float)}), without taking into account - * any default values. - * - * @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}, {@link - * #VERTICAL}, {@link #HORIZONTAL}, {@link #ALL} - */ - public float getRaw(int spacingType) { - return mSpacing[spacingType]; - } - - /** - * Resets the spacing instance to its default state. This method is meant to be used when - * recycling {@link Spacing} instances. - */ - public void reset() { - Arrays.fill(mSpacing, YogaConstants.UNDEFINED); - mHasAliasesSet = false; - mValueFlags = 0; - } - - /** - * Try to get start value and fallback to given type if not defined. This is used privately by the - * layout engine as a more efficient way to fetch direction-aware values by avoid extra method - * invocations. - */ - float getWithFallback(int spacingType, int fallbackType) { - return (mValueFlags & sFlagsMap[spacingType]) != 0 ? mSpacing[spacingType] : get(fallbackType); - } - - private static float[] newFullSpacingArray() { - return new float[] { - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - YogaConstants.UNDEFINED, - }; - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.kt new file mode 100644 index 00000000000..baff9be3a78 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.kt @@ -0,0 +1,203 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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.react.uimanager + +import com.facebook.react.uimanager.FloatUtil.floatsEqual +import com.facebook.yoga.YogaConstants + +/** + * Class representing CSS spacing (padding, margin, and borders). This is mostly necessary to + * properly implement interactions and updates for properties like margin, marginLeft, and + * marginHorizontal. + */ +public class Spacing(private val defaultValue: Float, private val spacing: FloatArray) { + private var valueFlags = 0 + private var hasAliasesSet = false + + public constructor() : this(0f, newFullSpacingArray()) {} + + public constructor(defaultValue: Float) : this(defaultValue, newFullSpacingArray()) {} + + /** + * Copy constructor. + * + * @param original the original [Spacing] to copy + */ + public constructor(original: Spacing) : this(original.defaultValue, original.spacing.copyOf()) { + valueFlags = original.valueFlags + hasAliasesSet = original.hasAliasesSet + } + + /** + * Set a spacing value. + * + * @param spacingType one of [.LEFT], [.TOP], [.RIGHT], [.BOTTOM], [ ][.VERTICAL], [.HORIZONTAL], + * [.ALL] + * @param value the value for this direction + * @return `true` if the spacing has changed, or `false` if the same value was already set + */ + public operator fun set(spacingType: Int, value: Float): Boolean { + if (!floatsEqual(spacing[spacingType], value)) { + spacing[spacingType] = value + valueFlags = + if (YogaConstants.isUndefined(value)) { + valueFlags and flagsMap[spacingType].inv() + } else { + valueFlags or flagsMap[spacingType] + } + hasAliasesSet = + valueFlags and flagsMap[ALL] != 0 || + valueFlags and flagsMap[VERTICAL] != 0 || + valueFlags and flagsMap[HORIZONTAL] != 0 || + valueFlags and flagsMap[BLOCK] != 0 + return true + } + return false + } + + /** + * Get the spacing for a direction. This takes into account any default values that have been set. + * + * @param spacingType one of [.LEFT], [.TOP], [.RIGHT], [.BOTTOM] + */ + public operator fun get(spacingType: Int): Float { + val defaultVal = + if (spacingType == START || + spacingType == END || + spacingType == BLOCK || + spacingType == BLOCK_END || + spacingType == BLOCK_START) { + YogaConstants.UNDEFINED + } else { + defaultValue + } + if (valueFlags == 0) { + return defaultVal + } + if ((valueFlags and flagsMap[spacingType]) != 0) { + return spacing[spacingType] + } + if (hasAliasesSet) { + val secondType = if (spacingType == TOP || spacingType == BOTTOM) VERTICAL else HORIZONTAL + if (valueFlags and flagsMap[secondType] != 0) { + return spacing[secondType] + } else if (valueFlags and flagsMap[ALL] != 0) { + return spacing[ALL] + } + } + return defaultVal + } + + /** + * Get the raw value (that was set using [.set]), without taking into account any default values. + * + * @param spacingType one of [.LEFT], [.TOP], [.RIGHT], [.BOTTOM], [ ][.VERTICAL], [.HORIZONTAL], + * [.ALL] + */ + public fun getRaw(spacingType: Int): Float = spacing[spacingType] + + /** + * Resets the spacing instance to its default state. This method is meant to be used when + * recycling [Spacing] instances. + */ + public fun reset() { + spacing.fill(YogaConstants.UNDEFINED) + hasAliasesSet = false + valueFlags = 0 + } + + /** + * Try to get start value and fallback to given type if not defined. This is used privately by the + * layout engine as a more efficient way to fetch direction-aware values by avoid extra method + * invocations. + */ + public fun getWithFallback(spacingType: Int, fallbackType: Int): Float { + return if (valueFlags and flagsMap[spacingType] != 0) { + spacing[spacingType] + } else { + get(fallbackType) + } + } + + public companion object { + /** Spacing type that represents the left direction. E.g. `marginLeft`. */ + public const val LEFT: Int = 0 + + /** Spacing type that represents the top direction. E.g. `marginTop`. */ + public const val TOP: Int = 1 + + /** Spacing type that represents the right direction. E.g. `marginRight`. */ + public const val RIGHT: Int = 2 + + /** Spacing type that represents the bottom direction. E.g. `marginBottom`. */ + public const val BOTTOM: Int = 3 + + /** + * Spacing type that represents start direction e.g. left in left-to-right, right in + * right-to-left. + */ + public const val START: Int = 4 + + /** + * Spacing type that represents end direction e.g. right in left-to-right, left in + * right-to-left. + */ + public const val END: Int = 5 + + /** + * Spacing type that represents horizontal direction (left and right). E.g. `marginHorizontal`. + */ + public const val HORIZONTAL: Int = 6 + + /** Spacing type that represents vertical direction (top and bottom). E.g. `marginVertical`. */ + public const val VERTICAL: Int = 7 + + /** Spacing type that represents all directions (left, top, right, bottom). E.g. `margin`. */ + public const val ALL: Int = 8 + + /** Spacing type that represents block directions (top, bottom). E.g. `marginBlock`. */ + public const val BLOCK: Int = 9 + + /** Spacing type that represents the block end direction (bottom). E.g. `marginBlockEnd`. */ + public const val BLOCK_END: Int = 10 + + /** Spacing type that represents the block start direction (top). E.g. `marginBlockStart`. */ + public const val BLOCK_START: Int = 11 + + private val flagsMap = + intArrayOf( + 1, /*LEFT*/ + 2, /*TOP*/ + 4, /*RIGHT*/ + 8, /*BOTTOM*/ + 16, /*START*/ + 32, /*END*/ + 64, /*HORIZONTAL*/ + 128, /*VERTICAL*/ + 256, /*ALL*/ + 512, /*BLOCK*/ + 1024, /*BLOCK_END*/ + 2048) + + private fun newFullSpacingArray(): FloatArray { + return floatArrayOf( + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED, + YogaConstants.UNDEFINED) + } + } +}