Files
yoga/java/com/facebook/csslayout/Spacing.java
Emil Sjolander a960203567 Use single function for margin, position, padding, and border
Summary:
marginLeft(node, margin) -> margin(node, CSSEdgeLeft, margin)

This reduces the api surface of CSSLayout as well as puts the api more in line with the java version. This also adds support for CSSEdgeAll which java has had support for for a while. This also open up the possibility of doing margin(node, CSSEdgeLeft | CSSEdgeTop, margin) in the future.

Reviewed By: lucasr

Differential Revision: D3715201

fbshipit-source-id: ea81ed426f0f7853bb542355c01fc16ae4360238
2016-08-15 09:23:28 -07:00

222 lines
6.5 KiB
Java

/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.csslayout;
import javax.annotation.Nullable;
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.
*/
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;
private static final int[] sFlagsMap = {
1, /*LEFT*/
2, /*TOP*/
4, /*RIGHT*/
8, /*BOTTOM*/
16, /*START*/
32, /*END*/
64, /*HORIZONTAL*/
128, /*VERTICAL*/
256, /*ALL*/
};
private final float[] mSpacing = newFullSpacingArray();
@Nullable private float[] mDefaultSpacing = null;
private int mValueFlags = 0;
private boolean 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 (CSSConstants.isUndefined(value)) {
mValueFlags &= ~sFlagsMap[spacingType];
} else {
mValueFlags |= sFlagsMap[spacingType];
}
mHasAliasesSet =
(mValueFlags & sFlagsMap[ALL]) != 0 ||
(mValueFlags & sFlagsMap[VERTICAL]) != 0 ||
(mValueFlags & sFlagsMap[HORIZONTAL]) != 0;
return true;
}
return false;
}
/**
* Set a default spacing value. This is used as a fallback when no spacing has been set for a
* particular direction.
*
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}
* @param value the default value for this direction
* @return
*/
public boolean setDefault(int spacingType, float value) {
if (mDefaultSpacing == null) {
mDefaultSpacing = newSpacingResultArray();
}
if (!FloatUtil.floatsEqual(mDefaultSpacing[spacingType], value)) {
mDefaultSpacing[spacingType] = value;
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 = (mDefaultSpacing != null)
? mDefaultSpacing[spacingType]
: (spacingType == START || spacingType == END ? CSSConstants.UNDEFINED : 0);
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.
*/
void reset() {
Arrays.fill(mSpacing, CSSConstants.UNDEFINED);
mDefaultSpacing = null;
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[] {
CSSConstants.UNDEFINED,
CSSConstants.UNDEFINED,
CSSConstants.UNDEFINED,
CSSConstants.UNDEFINED,
CSSConstants.UNDEFINED,
CSSConstants.UNDEFINED,
CSSConstants.UNDEFINED,
CSSConstants.UNDEFINED,
CSSConstants.UNDEFINED,
};
}
private static float[] newSpacingResultArray() {
return newSpacingResultArray(0);
}
private static float[] newSpacingResultArray(float defaultValue) {
return new float[] {
defaultValue,
defaultValue,
defaultValue,
defaultValue,
CSSConstants.UNDEFINED,
CSSConstants.UNDEFINED,
defaultValue,
defaultValue,
defaultValue,
};
}
}