Add percentage support to react native
Summary: Adds support for percentage value in react native. syntax: property: 100 | property | '100%' supported properties: padding margin width height minWidth minHeight maxWidth maxHeight flexBasis ``` class Playground extends React.Component { render() { return ( <View style={{backgroundColor: 'white', padding: 10, paddingTop: 30, height: '100%'}}> <Text> If you want to quickly test out something, open the Playground.js file and start coding. </Text> <View style={{backgroundColor: 'red', height: 50, width: 50}}/> <View style={{backgroundColor: 'blue', height: '50%', width: '50%'}}/> </View> ); } } ``` Reviewed By: astreet Differential Revision: D4376549 fbshipit-source-id: c41d68a7555396f95d063a7527ee081773ac56dc
This commit is contained in:
parent
00d5674474
commit
3f49e743be
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
@interface RCTConvert_YGValueTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTConvert_YGValueTests
|
||||
|
||||
- (void)testUndefined
|
||||
{
|
||||
YGValue value = [RCTConvert YGValue:nil];
|
||||
XCTAssertEqual(value.unit, YGUnitUndefined);
|
||||
}
|
||||
|
||||
- (void)testNumberPoints
|
||||
{
|
||||
YGValue value = [RCTConvert YGValue:@100];
|
||||
XCTAssertEqual(value.unit, YGUnitPixel);
|
||||
XCTAssertEqual(value.value, 100);
|
||||
}
|
||||
|
||||
- (void)testStringPercent
|
||||
{
|
||||
YGValue value = [RCTConvert YGValue:@"100%"];
|
||||
XCTAssertEqual(value.unit, YGUnitPercent);
|
||||
XCTAssertEqual(value.value, 100);
|
||||
}
|
||||
|
||||
@end
|
|
@ -30,184 +30,256 @@ var LayoutPropTypes = {
|
|||
/** `width` sets the width of this component.
|
||||
*
|
||||
* It works similarly to `width` in CSS, but in React Native you
|
||||
* must use logical pixel units, rather than percents, ems, or any of that.
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/width for more details.
|
||||
*/
|
||||
width: ReactPropTypes.number,
|
||||
width: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `height` sets the height of this component.
|
||||
*
|
||||
* It works similarly to `height` in CSS, but in React Native you
|
||||
* must use logical pixel units, rather than percents, ems, or any of that.
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/height for more details.
|
||||
*/
|
||||
height: ReactPropTypes.number,
|
||||
height: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `top` is the number of logical pixels to offset the top edge of
|
||||
* this component.
|
||||
*
|
||||
* It works similarly to `top` in CSS, but in React Native you must
|
||||
* use logical pixel units, rather than percents, ems, or any of that.
|
||||
* It works similarly to `top` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/top
|
||||
* for more details of how `top` affects layout.
|
||||
*/
|
||||
top: ReactPropTypes.number,
|
||||
top: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `left` is the number of logical pixels to offset the left edge of
|
||||
* this component.
|
||||
*
|
||||
* It works similarly to `left` in CSS, but in React Native you must
|
||||
* use logical pixel units, rather than percents, ems, or any of that.
|
||||
* It works similarly to `left` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/left
|
||||
* for more details of how `left` affects layout.
|
||||
*/
|
||||
left: ReactPropTypes.number,
|
||||
left: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `right` is the number of logical pixels to offset the right edge of
|
||||
* this component.
|
||||
*
|
||||
* It works similarly to `right` in CSS, but in React Native you must
|
||||
* use logical pixel units, rather than percents, ems, or any of that.
|
||||
* It works similarly to `right` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/right
|
||||
* for more details of how `right` affects layout.
|
||||
*/
|
||||
right: ReactPropTypes.number,
|
||||
right: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `bottom` is the number of logical pixels to offset the bottom edge of
|
||||
* this component.
|
||||
*
|
||||
* It works similarly to `bottom` in CSS, but in React Native you must
|
||||
* use logical pixel units, rather than percents, ems, or any of that.
|
||||
* It works similarly to `bottom` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/bottom
|
||||
* for more details of how `bottom` affects layout.
|
||||
*/
|
||||
bottom: ReactPropTypes.number,
|
||||
bottom: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `minWidth` is the minimum width for this component, in logical pixels.
|
||||
*
|
||||
* It works similarly to `min-width` in CSS, but in React Native you
|
||||
* must use logical pixel units, rather than percents, ems, or any of that.
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/min-width
|
||||
* for more details.
|
||||
*/
|
||||
minWidth: ReactPropTypes.number,
|
||||
minWidth: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `maxWidth` is the maximum width for this component, in logical pixels.
|
||||
*
|
||||
* It works similarly to `max-width` in CSS, but in React Native you
|
||||
* must use logical pixel units, rather than percents, ems, or any of that.
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/max-width
|
||||
* for more details.
|
||||
*/
|
||||
maxWidth: ReactPropTypes.number,
|
||||
maxWidth: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `minHeight` is the minimum height for this component, in logical pixels.
|
||||
*
|
||||
* It works similarly to `min-height` in CSS, but in React Native you
|
||||
* must use logical pixel units, rather than percents, ems, or any of that.
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/min-height
|
||||
* for more details.
|
||||
*/
|
||||
minHeight: ReactPropTypes.number,
|
||||
minHeight: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `maxHeight` is the maximum height for this component, in logical pixels.
|
||||
*
|
||||
* It works similarly to `max-height` in CSS, but in React Native you
|
||||
* must use logical pixel units, rather than percents, ems, or any of that.
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/max-height
|
||||
* for more details.
|
||||
*/
|
||||
maxHeight: ReactPropTypes.number,
|
||||
maxHeight: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** Setting `margin` has the same effect as setting each of
|
||||
* `marginTop`, `marginLeft`, `marginBottom`, and `marginRight`.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/margin
|
||||
* for more details.
|
||||
*/
|
||||
margin: ReactPropTypes.number,
|
||||
margin: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** Setting `marginVertical` has the same effect as setting both
|
||||
* `marginTop` and `marginBottom`.
|
||||
*/
|
||||
marginVertical: ReactPropTypes.number,
|
||||
marginVertical: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** Setting `marginHorizontal` has the same effect as setting
|
||||
* both `marginLeft` and `marginRight`.
|
||||
*/
|
||||
marginHorizontal: ReactPropTypes.number,
|
||||
marginHorizontal: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `marginTop` works like `margin-top` in CSS.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top
|
||||
* for more details.
|
||||
*/
|
||||
marginTop: ReactPropTypes.number,
|
||||
marginTop: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `marginBottom` works like `margin-bottom` in CSS.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom
|
||||
* for more details.
|
||||
*/
|
||||
marginBottom: ReactPropTypes.number,
|
||||
marginBottom: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `marginLeft` works like `margin-left` in CSS.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left
|
||||
* for more details.
|
||||
*/
|
||||
marginLeft: ReactPropTypes.number,
|
||||
marginLeft: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `marginRight` works like `margin-right` in CSS.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-right
|
||||
* for more details.
|
||||
*/
|
||||
marginRight: ReactPropTypes.number,
|
||||
marginRight: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** Setting `padding` has the same effect as setting each of
|
||||
* `paddingTop`, `paddingBottom`, `paddingLeft`, and `paddingRight`.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
* for more details.
|
||||
*/
|
||||
padding: ReactPropTypes.number,
|
||||
padding: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** Setting `paddingVertical` is like setting both of
|
||||
* `paddingTop` and `paddingBottom`.
|
||||
*/
|
||||
paddingVertical: ReactPropTypes.number,
|
||||
paddingVertical: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** Setting `paddingHorizontal` is like setting both of
|
||||
* `paddingLeft` and `paddingRight`.
|
||||
*/
|
||||
paddingHorizontal: ReactPropTypes.number,
|
||||
paddingHorizontal: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `paddingTop` works like `padding-top` in CSS.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-top
|
||||
* for more details.
|
||||
*/
|
||||
paddingTop: ReactPropTypes.number,
|
||||
paddingTop: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `paddingBottom` works like `padding-bottom` in CSS.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom
|
||||
* for more details.
|
||||
*/
|
||||
paddingBottom: ReactPropTypes.number,
|
||||
paddingBottom: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `paddingLeft` works like `padding-left` in CSS.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left
|
||||
* for more details.
|
||||
*/
|
||||
paddingLeft: ReactPropTypes.number,
|
||||
paddingLeft: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `paddingRight` works like `padding-right` in CSS.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-right
|
||||
* for more details.
|
||||
*/
|
||||
paddingRight: ReactPropTypes.number,
|
||||
paddingRight: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/** `borderWidth` works like `border-width` in CSS.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/border-width
|
||||
|
@ -365,7 +437,10 @@ var LayoutPropTypes = {
|
|||
flex: ReactPropTypes.number,
|
||||
flexGrow: ReactPropTypes.number,
|
||||
flexShrink: ReactPropTypes.number,
|
||||
flexBasis: ReactPropTypes.number,
|
||||
flexBasis: ReactPropTypes.oneOfType([
|
||||
ReactPropTypes.number,
|
||||
ReactPropTypes.string,
|
||||
]),
|
||||
|
||||
/**
|
||||
* Aspect ratio control the size of the undefined dimension of a node. Aspect ratio is a
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <yoga/Yoga.h>
|
||||
#import <React/RCTAnimationType.h>
|
||||
#import <React/RCTBorderStyle.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTPointerEvents.h>
|
||||
#import <React/RCTTextDecorationLineType.h>
|
||||
#import <yoga/Yoga.h>
|
||||
|
||||
/**
|
||||
* This class provides a collection of conversion functions for mapping
|
||||
|
@ -90,6 +90,8 @@ typedef NSURL RCTFileURL;
|
|||
+ (UIColor *)UIColor:(id)json;
|
||||
+ (CGColorRef)CGColor:(id)json CF_RETURNS_NOT_RETAINED;
|
||||
|
||||
+ (YGValue)YGValue:(id)json;
|
||||
|
||||
+ (NSArray<NSArray *> *)NSArrayArray:(id)json;
|
||||
+ (NSArray<NSString *> *)NSStringArray:(id)json;
|
||||
+ (NSArray<NSArray<NSString *> *> *)NSStringArrayArray:(id)json;
|
||||
|
|
|
@ -496,6 +496,25 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[
|
|||
return [self UIColor:json].CGColor;
|
||||
}
|
||||
|
||||
+ (YGValue)YGValue:(id)json
|
||||
{
|
||||
if (!json) {
|
||||
return YGValueUndefined;
|
||||
} else if ([json isKindOfClass:[NSNumber class]]) {
|
||||
return (YGValue) { [json floatValue], YGUnitPixel };
|
||||
} else if ([json isKindOfClass:[NSString class]]) {
|
||||
NSString *s = (NSString *) json;
|
||||
if ([s hasSuffix:@"%"]) {
|
||||
return (YGValue) { [[s substringToIndex:s.length] floatValue], YGUnitPercent };
|
||||
} else {
|
||||
RCTLogConvertError(json, @"a YGValue. Did you forget the % or pt suffix?");
|
||||
}
|
||||
} else {
|
||||
RCTLogConvertError(json, @"a YGValue.");
|
||||
}
|
||||
return YGValueUndefined;
|
||||
}
|
||||
|
||||
NSArray *RCTConvertArrayValue(SEL type, id json)
|
||||
{
|
||||
__block BOOL copy = NO;
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <yoga/Yoga.h>
|
||||
#import <React/RCTComponent.h>
|
||||
#import <React/RCTRootView.h>
|
||||
#import <yoga/Yoga.h>
|
||||
|
||||
@class RCTSparseArray;
|
||||
|
||||
|
@ -66,18 +66,18 @@ typedef void (^RCTApplierBlock)(NSDictionary<NSNumber *, UIView *> *viewRegistry
|
|||
* Position and dimensions.
|
||||
* Defaults to { 0, 0, NAN, NAN }.
|
||||
*/
|
||||
@property (nonatomic, assign) float top;
|
||||
@property (nonatomic, assign) float left;
|
||||
@property (nonatomic, assign) float bottom;
|
||||
@property (nonatomic, assign) float right;
|
||||
@property (nonatomic, assign) YGValue top;
|
||||
@property (nonatomic, assign) YGValue left;
|
||||
@property (nonatomic, assign) YGValue bottom;
|
||||
@property (nonatomic, assign) YGValue right;
|
||||
|
||||
@property (nonatomic, assign) float width;
|
||||
@property (nonatomic, assign) float height;
|
||||
@property (nonatomic, assign) YGValue width;
|
||||
@property (nonatomic, assign) YGValue height;
|
||||
|
||||
@property (nonatomic, assign) float minWidth;
|
||||
@property (nonatomic, assign) float maxWidth;
|
||||
@property (nonatomic, assign) float minHeight;
|
||||
@property (nonatomic, assign) float maxHeight;
|
||||
@property (nonatomic, assign) YGValue minWidth;
|
||||
@property (nonatomic, assign) YGValue maxWidth;
|
||||
@property (nonatomic, assign) YGValue minHeight;
|
||||
@property (nonatomic, assign) YGValue maxHeight;
|
||||
|
||||
@property (nonatomic, assign) CGRect frame;
|
||||
|
||||
|
@ -102,24 +102,24 @@ typedef void (^RCTApplierBlock)(NSDictionary<NSNumber *, UIView *> *viewRegistry
|
|||
/**
|
||||
* Margin. Defaults to { 0, 0, 0, 0 }.
|
||||
*/
|
||||
@property (nonatomic, assign) float margin;
|
||||
@property (nonatomic, assign) float marginVertical;
|
||||
@property (nonatomic, assign) float marginHorizontal;
|
||||
@property (nonatomic, assign) float marginTop;
|
||||
@property (nonatomic, assign) float marginLeft;
|
||||
@property (nonatomic, assign) float marginBottom;
|
||||
@property (nonatomic, assign) float marginRight;
|
||||
@property (nonatomic, assign) YGValue margin;
|
||||
@property (nonatomic, assign) YGValue marginVertical;
|
||||
@property (nonatomic, assign) YGValue marginHorizontal;
|
||||
@property (nonatomic, assign) YGValue marginTop;
|
||||
@property (nonatomic, assign) YGValue marginLeft;
|
||||
@property (nonatomic, assign) YGValue marginBottom;
|
||||
@property (nonatomic, assign) YGValue marginRight;
|
||||
|
||||
/**
|
||||
* Padding. Defaults to { 0, 0, 0, 0 }.
|
||||
*/
|
||||
@property (nonatomic, assign) float padding;
|
||||
@property (nonatomic, assign) float paddingVertical;
|
||||
@property (nonatomic, assign) float paddingHorizontal;
|
||||
@property (nonatomic, assign) float paddingTop;
|
||||
@property (nonatomic, assign) float paddingLeft;
|
||||
@property (nonatomic, assign) float paddingBottom;
|
||||
@property (nonatomic, assign) float paddingRight;
|
||||
@property (nonatomic, assign) YGValue padding;
|
||||
@property (nonatomic, assign) YGValue paddingVertical;
|
||||
@property (nonatomic, assign) YGValue paddingHorizontal;
|
||||
@property (nonatomic, assign) YGValue paddingTop;
|
||||
@property (nonatomic, assign) YGValue paddingLeft;
|
||||
@property (nonatomic, assign) YGValue paddingBottom;
|
||||
@property (nonatomic, assign) YGValue paddingRight;
|
||||
|
||||
- (UIEdgeInsets)paddingAsInsets;
|
||||
|
||||
|
@ -135,7 +135,7 @@ typedef void (^RCTApplierBlock)(NSDictionary<NSNumber *, UIView *> *viewRegistry
|
|||
|
||||
@property (nonatomic, assign) float flexGrow;
|
||||
@property (nonatomic, assign) float flexShrink;
|
||||
@property (nonatomic, assign) float flexBasis;
|
||||
@property (nonatomic, assign) YGValue flexBasis;
|
||||
|
||||
@property (nonatomic, assign) float aspectRatio;
|
||||
|
||||
|
|
|
@ -41,9 +41,9 @@ typedef NS_ENUM(unsigned int, meta_prop_t) {
|
|||
BOOL _recomputeMargin;
|
||||
BOOL _recomputeBorder;
|
||||
BOOL _didUpdateSubviews;
|
||||
float _paddingMetaProps[META_PROP_COUNT];
|
||||
float _marginMetaProps[META_PROP_COUNT];
|
||||
float _borderMetaProps[META_PROP_COUNT];
|
||||
YGValue _paddingMetaProps[META_PROP_COUNT];
|
||||
YGValue _marginMetaProps[META_PROP_COUNT];
|
||||
YGValue _borderMetaProps[META_PROP_COUNT];
|
||||
}
|
||||
|
||||
@synthesize reactTag = _reactTag;
|
||||
|
@ -56,20 +56,42 @@ static void RCTPrint(YGNodeRef node)
|
|||
printf("%s(%zd), ", shadowView.viewName.UTF8String, shadowView.reactTag.integerValue);
|
||||
}
|
||||
|
||||
#define RCT_SET_YGVALUE(ygvalue, setter, ...) \
|
||||
switch (ygvalue.unit) { \
|
||||
case YGUnitUndefined: \
|
||||
setter(__VA_ARGS__, YGUndefined); \
|
||||
break; \
|
||||
case YGUnitPixel: \
|
||||
setter(__VA_ARGS__, ygvalue.value); \
|
||||
break; \
|
||||
case YGUnitPercent: \
|
||||
setter##Percent(__VA_ARGS__, ygvalue.value); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define DEFINE_PROCESS_META_PROPS(type) \
|
||||
static void RCTProcessMetaProps##type(const float metaProps[META_PROP_COUNT], YGNodeRef node) { \
|
||||
YGNodeStyleSet##type(node, YGEdgeStart, metaProps[META_PROP_LEFT]); \
|
||||
YGNodeStyleSet##type(node, YGEdgeEnd, metaProps[META_PROP_RIGHT]); \
|
||||
YGNodeStyleSet##type(node, YGEdgeTop, metaProps[META_PROP_TOP]); \
|
||||
YGNodeStyleSet##type(node, YGEdgeBottom, metaProps[META_PROP_BOTTOM]); \
|
||||
YGNodeStyleSet##type(node, YGEdgeHorizontal, metaProps[META_PROP_HORIZONTAL]); \
|
||||
YGNodeStyleSet##type(node, YGEdgeVertical, metaProps[META_PROP_VERTICAL]); \
|
||||
YGNodeStyleSet##type(node, YGEdgeAll, metaProps[META_PROP_ALL]); \
|
||||
static void RCTProcessMetaProps##type(const YGValue metaProps[META_PROP_COUNT], YGNodeRef node) { \
|
||||
RCT_SET_YGVALUE(metaProps[META_PROP_LEFT], YGNodeStyleSet##type, node, YGEdgeStart); \
|
||||
RCT_SET_YGVALUE(metaProps[META_PROP_RIGHT], YGNodeStyleSet##type, node, YGEdgeEnd); \
|
||||
RCT_SET_YGVALUE(metaProps[META_PROP_TOP], YGNodeStyleSet##type, node, YGEdgeTop); \
|
||||
RCT_SET_YGVALUE(metaProps[META_PROP_BOTTOM], YGNodeStyleSet##type, node, YGEdgeBottom); \
|
||||
RCT_SET_YGVALUE(metaProps[META_PROP_HORIZONTAL], YGNodeStyleSet##type, node, YGEdgeHorizontal); \
|
||||
RCT_SET_YGVALUE(metaProps[META_PROP_VERTICAL], YGNodeStyleSet##type, node, YGEdgeVertical); \
|
||||
RCT_SET_YGVALUE(metaProps[META_PROP_ALL], YGNodeStyleSet##type, node, YGEdgeAll); \
|
||||
}
|
||||
|
||||
DEFINE_PROCESS_META_PROPS(Padding);
|
||||
DEFINE_PROCESS_META_PROPS(Margin);
|
||||
DEFINE_PROCESS_META_PROPS(Border);
|
||||
|
||||
static void RCTProcessMetaPropsBorder(const YGValue metaProps[META_PROP_COUNT], YGNodeRef node) {
|
||||
YGNodeStyleSetBorder(node, YGEdgeStart, metaProps[META_PROP_LEFT].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeEnd, metaProps[META_PROP_RIGHT].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeTop, metaProps[META_PROP_TOP].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeBottom, metaProps[META_PROP_BOTTOM].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeHorizontal, metaProps[META_PROP_HORIZONTAL].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeVertical, metaProps[META_PROP_VERTICAL].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeAll, metaProps[META_PROP_ALL].value);
|
||||
}
|
||||
|
||||
// The absolute stuff is so that we can take into account our absolute position when rounding in order to
|
||||
// snap to the pixel grid. For example, say you have the following structure:
|
||||
|
@ -112,7 +134,7 @@ DEFINE_PROCESS_META_PROPS(Border);
|
|||
#if RCT_DEBUG
|
||||
// This works around a breaking change in css-layout where setting flexBasis needs to be set explicitly, instead of relying on flex to propagate.
|
||||
// We check for it by seeing if a width/height is provided along with a flexBasis of 0 and the width/height is laid out as 0.
|
||||
if ((YGNodeStyleGetFlexBasis(node).unit == YGUnitPixel && YGNodeStyleGetFlexBasis(node).value == 0) &&
|
||||
if (YGNodeStyleGetFlexBasis(node).unit == YGUnitPixel && YGNodeStyleGetFlexBasis(node).value == 0 &&
|
||||
((YGNodeStyleGetWidth(node).unit == YGUnitPixel && YGNodeStyleGetWidth(node).value > 0 && YGNodeLayoutGetWidth(node) == 0) ||
|
||||
(YGNodeStyleGetHeight(node).unit == YGUnitPixel && YGNodeStyleGetHeight(node).value > 0 && YGNodeLayoutGetHeight(node) == 0))) {
|
||||
RCTLogError(@"View was rendered with explicitly set width/height but with a 0 flexBasis. (This might be fixed by changing flex: to flexGrow:) View: %@", self);
|
||||
|
@ -274,9 +296,9 @@ DEFINE_PROCESS_META_PROPS(Border);
|
|||
_frame = CGRectMake(0, 0, YGUndefined, YGUndefined);
|
||||
|
||||
for (unsigned int ii = 0; ii < META_PROP_COUNT; ii++) {
|
||||
_paddingMetaProps[ii] = YGUndefined;
|
||||
_marginMetaProps[ii] = YGUndefined;
|
||||
_borderMetaProps[ii] = YGUndefined;
|
||||
_paddingMetaProps[ii] = YGValueUndefined;
|
||||
_marginMetaProps[ii] = YGValueUndefined;
|
||||
_borderMetaProps[ii] = YGValueUndefined;
|
||||
}
|
||||
|
||||
_newView = YES;
|
||||
|
@ -417,12 +439,12 @@ DEFINE_PROCESS_META_PROPS(Border);
|
|||
// Margin
|
||||
|
||||
#define RCT_MARGIN_PROPERTY(prop, metaProp) \
|
||||
- (void)setMargin##prop:(float)value \
|
||||
- (void)setMargin##prop:(YGValue)value \
|
||||
{ \
|
||||
_marginMetaProps[META_PROP_##metaProp] = value; \
|
||||
_recomputeMargin = YES; \
|
||||
} \
|
||||
- (float)margin##prop \
|
||||
- (YGValue)margin##prop \
|
||||
{ \
|
||||
return _marginMetaProps[META_PROP_##metaProp]; \
|
||||
}
|
||||
|
@ -438,12 +460,12 @@ RCT_MARGIN_PROPERTY(Right, RIGHT)
|
|||
// Padding
|
||||
|
||||
#define RCT_PADDING_PROPERTY(prop, metaProp) \
|
||||
- (void)setPadding##prop:(float)value \
|
||||
- (void)setPadding##prop:(YGValue)value \
|
||||
{ \
|
||||
_paddingMetaProps[META_PROP_##metaProp] = value; \
|
||||
_recomputePadding = YES; \
|
||||
} \
|
||||
- (float)padding##prop \
|
||||
- (YGValue)padding##prop \
|
||||
{ \
|
||||
return _paddingMetaProps[META_PROP_##metaProp]; \
|
||||
}
|
||||
|
@ -471,12 +493,12 @@ RCT_PADDING_PROPERTY(Right, RIGHT)
|
|||
#define RCT_BORDER_PROPERTY(prop, metaProp) \
|
||||
- (void)setBorder##prop##Width:(float)value \
|
||||
{ \
|
||||
_borderMetaProps[META_PROP_##metaProp] = value; \
|
||||
_borderMetaProps[META_PROP_##metaProp].value = value; \
|
||||
_recomputeBorder = YES; \
|
||||
} \
|
||||
- (float)border##prop##Width \
|
||||
{ \
|
||||
return _borderMetaProps[META_PROP_##metaProp]; \
|
||||
return _borderMetaProps[META_PROP_##metaProp].value; \
|
||||
}
|
||||
|
||||
RCT_BORDER_PROPERTY(, ALL)
|
||||
|
@ -487,16 +509,15 @@ RCT_BORDER_PROPERTY(Right, RIGHT)
|
|||
|
||||
// Dimensions
|
||||
|
||||
|
||||
#define RCT_DIMENSION_PROPERTY(setProp, getProp, cssProp) \
|
||||
- (void)set##setProp:(float)value \
|
||||
- (void)set##setProp:(YGValue)value \
|
||||
{ \
|
||||
YGNodeStyleSet##cssProp(_cssNode, value); \
|
||||
RCT_SET_YGVALUE(value, YGNodeStyleSet##cssProp, _cssNode); \
|
||||
[self dirtyText]; \
|
||||
} \
|
||||
- (float)getProp \
|
||||
- (YGValue)getProp \
|
||||
{ \
|
||||
return YGNodeStyleGet##cssProp(_cssNode).value; \
|
||||
return YGNodeStyleGet##cssProp(_cssNode); \
|
||||
}
|
||||
|
||||
RCT_DIMENSION_PROPERTY(Width, width, Width)
|
||||
|
@ -509,14 +530,14 @@ RCT_DIMENSION_PROPERTY(MaxHeight, maxHeight, MaxHeight)
|
|||
// Position
|
||||
|
||||
#define RCT_POSITION_PROPERTY(setProp, getProp, edge) \
|
||||
- (void)set##setProp:(float)value \
|
||||
- (void)set##setProp:(YGValue)value \
|
||||
{ \
|
||||
YGNodeStyleSetPosition(_cssNode, edge, value); \
|
||||
RCT_SET_YGVALUE(value, YGNodeStyleSetPosition, _cssNode, edge); \
|
||||
[self dirtyText]; \
|
||||
} \
|
||||
- (float)getProp \
|
||||
- (YGValue)getProp \
|
||||
{ \
|
||||
return YGNodeStyleGetPosition(_cssNode, edge).value; \
|
||||
return YGNodeStyleGetPosition(_cssNode, edge); \
|
||||
}
|
||||
|
||||
RCT_POSITION_PROPERTY(Top, top, YGEdgeTop)
|
||||
|
@ -540,12 +561,12 @@ static inline void RCTAssignSuggestedDimension(YGNodeRef cssNode, YGDimension di
|
|||
if (amount != UIViewNoIntrinsicMetric) {
|
||||
switch (dimension) {
|
||||
case YGDimensionWidth:
|
||||
if (isnan(YGNodeStyleGetWidth(cssNode).value)) {
|
||||
if (YGNodeStyleGetWidth(cssNode).unit == YGUnitUndefined) {
|
||||
YGNodeStyleSetWidth(cssNode, amount);
|
||||
}
|
||||
break;
|
||||
case YGDimensionHeight:
|
||||
if (isnan(YGNodeStyleGetHeight(cssNode).value)) {
|
||||
if (YGNodeStyleGetHeight(cssNode).unit == YGUnitUndefined) {
|
||||
YGNodeStyleSetHeight(cssNode, amount);
|
||||
}
|
||||
break;
|
||||
|
@ -580,14 +601,14 @@ static inline void RCTAssignSuggestedDimension(YGNodeRef cssNode, YGDimension di
|
|||
YGNodeStyleSetFlex(_cssNode, value);
|
||||
}
|
||||
|
||||
- (void)setFlexBasis:(float)value
|
||||
- (void)setFlexBasis:(YGValue)value
|
||||
{
|
||||
YGNodeStyleSetFlexBasis(_cssNode, value);
|
||||
RCT_SET_YGVALUE(value, YGNodeStyleSetFlexBasis, _cssNode);
|
||||
}
|
||||
|
||||
- (float)flexBasis
|
||||
- (YGValue)flexBasis
|
||||
{
|
||||
return YGNodeStyleGetFlexBasis(_cssNode).value;
|
||||
return YGNodeStyleGetFlexBasis(_cssNode);
|
||||
}
|
||||
|
||||
#define RCT_STYLE_PROPERTY(setProp, getProp, cssProp, type) \
|
||||
|
|
|
@ -264,18 +264,18 @@ RCT_REMAP_VIEW_PROPERTY(zIndex, reactZIndex, NSInteger)
|
|||
|
||||
RCT_EXPORT_SHADOW_PROPERTY(backgroundColor, UIColor)
|
||||
|
||||
RCT_EXPORT_SHADOW_PROPERTY(top, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(right, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(bottom, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(left, float);
|
||||
RCT_EXPORT_SHADOW_PROPERTY(top, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(right, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(bottom, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(left, YGValue);
|
||||
|
||||
RCT_EXPORT_SHADOW_PROPERTY(width, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(height, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(width, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(height, YGValue)
|
||||
|
||||
RCT_EXPORT_SHADOW_PROPERTY(minWidth, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(maxWidth, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(minHeight, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(maxHeight, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(minWidth, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(maxWidth, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(minHeight, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(maxHeight, YGValue)
|
||||
|
||||
RCT_EXPORT_SHADOW_PROPERTY(borderTopWidth, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(borderRightWidth, float)
|
||||
|
@ -283,26 +283,26 @@ RCT_EXPORT_SHADOW_PROPERTY(borderBottomWidth, float)
|
|||
RCT_EXPORT_SHADOW_PROPERTY(borderLeftWidth, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(borderWidth, float)
|
||||
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginTop, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginRight, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginBottom, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginLeft, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginVertical, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginHorizontal, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(margin, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginTop, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginRight, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginBottom, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginLeft, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginVertical, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginHorizontal, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(margin, YGValue)
|
||||
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingTop, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingRight, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingBottom, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingLeft, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingVertical, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingHorizontal, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(padding, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingTop, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingRight, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingBottom, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingLeft, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingVertical, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(paddingHorizontal, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(padding, YGValue)
|
||||
|
||||
RCT_EXPORT_SHADOW_PROPERTY(flex, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(flexGrow, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(flexShrink, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(flexBasis, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(flexBasis, YGValue)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(flexDirection, YGFlexDirection)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(flexWrap, YGWrap)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(justifyContent, YGJustify)
|
||||
|
|
|
@ -24,6 +24,8 @@ import com.facebook.react.common.ReactConstants;
|
|||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.UIViewOperationQueue;
|
||||
import com.facebook.react.views.art.ARTVirtualNode;
|
||||
import com.facebook.yoga.YogaValue;
|
||||
import com.facebook.yoga.YogaUnit;
|
||||
|
||||
/* package */ class FlatARTSurfaceViewShadowNode extends FlatShadowNode
|
||||
implements AndroidView, TextureView.SurfaceTextureListener {
|
||||
|
@ -104,13 +106,24 @@ import com.facebook.react.views.art.ARTVirtualNode;
|
|||
|
||||
@Override
|
||||
public void setPadding(int spacingType, float padding) {
|
||||
if (getStylePadding(spacingType) != padding) {
|
||||
YogaValue current = getStylePadding(spacingType);
|
||||
if (current.unit != YogaUnit.PIXEL || current.value != padding) {
|
||||
super.setPadding(spacingType, padding);
|
||||
mPaddingChanged = true;
|
||||
markUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaddingPercent(int spacingType, float percent) {
|
||||
YogaValue current = getStylePadding(spacingType);
|
||||
if (current.unit != YogaUnit.PERCENT || current.value != percent) {
|
||||
super.setPadding(spacingType, percent);
|
||||
mPaddingChanged = true;
|
||||
markUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
|
||||
mSurface = new Surface(surface);
|
||||
|
|
|
@ -17,6 +17,8 @@ import android.view.Surface;
|
|||
import android.view.WindowManager;
|
||||
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.yoga.YogaValue;
|
||||
import com.facebook.yoga.YogaUnit;
|
||||
|
||||
/**
|
||||
* FlatReactModalShadowNode
|
||||
|
@ -86,10 +88,21 @@ class FlatReactModalShadowNode extends FlatShadowNode implements AndroidView {
|
|||
|
||||
@Override
|
||||
public void setPadding(int spacingType, float padding) {
|
||||
if (getStylePadding(spacingType) != padding) {
|
||||
YogaValue current = getStylePadding(spacingType);
|
||||
if (current.unit != YogaUnit.PIXEL || current.value != padding) {
|
||||
super.setPadding(spacingType, padding);
|
||||
mPaddingChanged = true;
|
||||
markUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaddingPercent(int spacingType, float percent) {
|
||||
YogaValue current = getStylePadding(spacingType);
|
||||
if (current.unit != YogaUnit.PERCENT || current.value != percent) {
|
||||
super.setPadding(spacingType, percent);
|
||||
mPaddingChanged = true;
|
||||
markUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ import com.facebook.react.uimanager.ThemedReactContext;
|
|||
import com.facebook.react.uimanager.UIViewOperationQueue;
|
||||
import com.facebook.react.uimanager.ViewGroupManager;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import com.facebook.yoga.YogaValue;
|
||||
import com.facebook.yoga.YogaUnit;
|
||||
|
||||
/* package */ final class NativeViewWrapper extends FlatShadowNode implements AndroidView {
|
||||
|
||||
|
@ -101,13 +103,24 @@ import com.facebook.react.uimanager.ViewManager;
|
|||
|
||||
@Override
|
||||
public void setPadding(int spacingType, float padding) {
|
||||
if (getStylePadding(spacingType) != padding) {
|
||||
YogaValue current = getStylePadding(spacingType);
|
||||
if (current.unit != YogaUnit.PIXEL || current.value != padding) {
|
||||
super.setPadding(spacingType, padding);
|
||||
mPaddingChanged = true;
|
||||
markUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaddingPercent(int spacingType, float percent) {
|
||||
YogaValue current = getStylePadding(spacingType);
|
||||
if (current.unit != YogaUnit.PERCENT || current.value != percent) {
|
||||
super.setPadding(spacingType, percent);
|
||||
mPaddingChanged = true;
|
||||
markUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) {
|
||||
if (mReactShadowNode != null && mReactShadowNode.hasUnseenUpdates()) {
|
||||
|
|
|
@ -6,12 +6,17 @@ import javax.annotation.Nullable;
|
|||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
import com.facebook.react.bridge.ReadableType;
|
||||
|
||||
import com.facebook.yoga.YogaAlign;
|
||||
import com.facebook.yoga.YogaConstants;
|
||||
import com.facebook.yoga.YogaFlexDirection;
|
||||
import com.facebook.yoga.YogaJustify;
|
||||
import com.facebook.yoga.YogaOverflow;
|
||||
import com.facebook.yoga.YogaPositionType;
|
||||
import com.facebook.yoga.YogaValue;
|
||||
import com.facebook.yoga.YogaUnit;
|
||||
import com.facebook.yoga.YogaWrap;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.uimanager.annotations.ReactPropGroup;
|
||||
|
@ -27,57 +32,107 @@ import com.facebook.react.uimanager.annotations.ReactPropGroup;
|
|||
*/
|
||||
public class LayoutShadowNode extends ReactShadowNode {
|
||||
|
||||
@ReactProp(name = ViewProps.WIDTH, defaultFloat = YogaConstants.UNDEFINED)
|
||||
public void setWidth(float width) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
setStyleWidth(YogaConstants.isUndefined(width) ? width : PixelUtil.toPixelFromDIP(width));
|
||||
private static boolean dynamicIsPercent(Dynamic dynamic) {
|
||||
return dynamic.getType() == ReadableType.String && dynamic.asString().endsWith("%");
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.MIN_WIDTH, defaultFloat = YogaConstants.UNDEFINED)
|
||||
public void setMinWidth(float minWidth) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
setStyleMinWidth(
|
||||
YogaConstants.isUndefined(minWidth) ? minWidth : PixelUtil.toPixelFromDIP(minWidth));
|
||||
private static float getDynamicAsPercent(Dynamic dynamic) {
|
||||
final String value = dynamic.asString();
|
||||
return Float.parseFloat(value.substring(0, value.length() - 1));
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.MAX_WIDTH, defaultFloat = YogaConstants.UNDEFINED)
|
||||
public void setMaxWidth(float maxWidth) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
setStyleMaxWidth(
|
||||
YogaConstants.isUndefined(maxWidth) ? maxWidth : PixelUtil.toPixelFromDIP(maxWidth));
|
||||
private static float getDynamicAsFloat(Dynamic dynamic) {
|
||||
return (float) PixelUtil.toPixelFromDIP(dynamic.asDouble());
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.HEIGHT, defaultFloat = YogaConstants.UNDEFINED)
|
||||
public void setHeight(float height) {
|
||||
@ReactProp(name = ViewProps.WIDTH)
|
||||
public void setWidth(Dynamic width) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
setStyleHeight(
|
||||
YogaConstants.isUndefined(height) ? height : PixelUtil.toPixelFromDIP(height));
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.MIN_HEIGHT, defaultFloat = YogaConstants.UNDEFINED)
|
||||
public void setMinHeight(float minHeight) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
setStyleMinHeight(
|
||||
YogaConstants.isUndefined(minHeight) ? minHeight : PixelUtil.toPixelFromDIP(minHeight));
|
||||
if (width != null && dynamicIsPercent(width)) {
|
||||
setStyleWidthPercent(getDynamicAsPercent(width));
|
||||
} else {
|
||||
setStyleWidth(width == null ? YogaConstants.UNDEFINED : getDynamicAsFloat(width));
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.MAX_HEIGHT, defaultFloat = YogaConstants.UNDEFINED)
|
||||
public void setMaxHeight(float maxHeight) {
|
||||
width.recycle();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.MIN_WIDTH)
|
||||
public void setMinWidth(Dynamic minWidth) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
setStyleMaxHeight(
|
||||
YogaConstants.isUndefined(maxHeight) ? maxHeight : PixelUtil.toPixelFromDIP(maxHeight));
|
||||
|
||||
if (minWidth != null && dynamicIsPercent(minWidth)) {
|
||||
setStyleMinWidthPercent(getDynamicAsPercent(minWidth));
|
||||
} else {
|
||||
setStyleMinWidth(minWidth == null ? YogaConstants.UNDEFINED : getDynamicAsFloat(minWidth));
|
||||
}
|
||||
|
||||
minWidth.recycle();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.MAX_WIDTH)
|
||||
public void setMaxWidth(Dynamic maxWidth) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (maxWidth != null && dynamicIsPercent(maxWidth)) {
|
||||
setStyleMaxWidthPercent(getDynamicAsPercent(maxWidth));
|
||||
} else {
|
||||
setStyleMaxWidth(maxWidth == null ? YogaConstants.UNDEFINED : getDynamicAsFloat(maxWidth));
|
||||
}
|
||||
|
||||
maxWidth.recycle();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.HEIGHT)
|
||||
public void setHeight(Dynamic height) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (height != null && dynamicIsPercent(height)) {
|
||||
setStyleHeightPercent(getDynamicAsPercent(height));
|
||||
} else {
|
||||
setStyleHeight(height == null ? YogaConstants.UNDEFINED : getDynamicAsFloat(height));
|
||||
}
|
||||
|
||||
height.recycle();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.MIN_HEIGHT)
|
||||
public void setMinHeight(Dynamic minHeight) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (minHeight != null && dynamicIsPercent(minHeight)) {
|
||||
setStyleMinHeightPercent(getDynamicAsPercent(minHeight));
|
||||
} else {
|
||||
setStyleMinHeight(minHeight == null ? YogaConstants.UNDEFINED : getDynamicAsFloat(minHeight));
|
||||
}
|
||||
|
||||
minHeight.recycle();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.MAX_HEIGHT)
|
||||
public void setMaxHeight(Dynamic maxHeight) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (maxHeight != null && dynamicIsPercent(maxHeight)) {
|
||||
setStyleMaxHeightPercent(getDynamicAsPercent(maxHeight));
|
||||
} else {
|
||||
setStyleMaxHeight(maxHeight == null ? YogaConstants.UNDEFINED : getDynamicAsFloat(maxHeight));
|
||||
}
|
||||
|
||||
maxHeight.recycle();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.FLEX, defaultFloat = 0f)
|
||||
|
@ -104,12 +159,19 @@ public class LayoutShadowNode extends ReactShadowNode {
|
|||
super.setFlexShrink(flexShrink);
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.FLEX_BASIS, defaultFloat = 0f)
|
||||
public void setFlexBasis(float flexBasis) {
|
||||
@ReactProp(name = ViewProps.FLEX_BASIS)
|
||||
public void setFlexBasis(Dynamic flexBasis) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
super.setFlexBasis(flexBasis);
|
||||
|
||||
if (flexBasis != null && dynamicIsPercent(flexBasis)) {
|
||||
setFlexBasisPercent(getDynamicAsPercent(flexBasis));
|
||||
} else {
|
||||
setFlexBasis(flexBasis == null ? 0 : getDynamicAsFloat(flexBasis));
|
||||
}
|
||||
|
||||
flexBasis.recycle();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.ASPECT_RATIO, defaultFloat = YogaConstants.UNDEFINED)
|
||||
|
@ -186,12 +248,21 @@ public class LayoutShadowNode extends ReactShadowNode {
|
|||
ViewProps.MARGIN_RIGHT,
|
||||
ViewProps.MARGIN_TOP,
|
||||
ViewProps.MARGIN_BOTTOM,
|
||||
}, defaultFloat = YogaConstants.UNDEFINED)
|
||||
public void setMargins(int index, float margin) {
|
||||
})
|
||||
public void setMargins(int index, Dynamic margin) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
setMargin(ViewProps.PADDING_MARGIN_SPACING_TYPES[index], PixelUtil.toPixelFromDIP(margin));
|
||||
|
||||
if (margin != null && dynamicIsPercent(margin)) {
|
||||
setMarginPercent(ViewProps.PADDING_MARGIN_SPACING_TYPES[index], getDynamicAsPercent(margin));
|
||||
} else {
|
||||
setMargin(
|
||||
ViewProps.PADDING_MARGIN_SPACING_TYPES[index],
|
||||
margin == null ? YogaConstants.UNDEFINED : getDynamicAsFloat(margin));
|
||||
}
|
||||
|
||||
margin.recycle();
|
||||
}
|
||||
|
||||
@ReactPropGroup(names = {
|
||||
|
@ -202,14 +273,22 @@ public class LayoutShadowNode extends ReactShadowNode {
|
|||
ViewProps.PADDING_RIGHT,
|
||||
ViewProps.PADDING_TOP,
|
||||
ViewProps.PADDING_BOTTOM,
|
||||
}, defaultFloat = YogaConstants.UNDEFINED)
|
||||
public void setPaddings(int index, float padding) {
|
||||
})
|
||||
public void setPaddings(int index, Dynamic padding) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (padding != null && dynamicIsPercent(padding)) {
|
||||
setPaddingPercent(
|
||||
ViewProps.PADDING_MARGIN_SPACING_TYPES[index], getDynamicAsPercent(padding));
|
||||
} else {
|
||||
setPadding(
|
||||
ViewProps.PADDING_MARGIN_SPACING_TYPES[index],
|
||||
YogaConstants.isUndefined(padding) ? padding : PixelUtil.toPixelFromDIP(padding));
|
||||
padding == null ? YogaConstants.UNDEFINED : getDynamicAsFloat(padding));
|
||||
}
|
||||
|
||||
padding.recycle();
|
||||
}
|
||||
|
||||
@ReactPropGroup(names = {
|
||||
|
@ -231,14 +310,21 @@ public class LayoutShadowNode extends ReactShadowNode {
|
|||
ViewProps.RIGHT,
|
||||
ViewProps.TOP,
|
||||
ViewProps.BOTTOM,
|
||||
}, defaultFloat = YogaConstants.UNDEFINED)
|
||||
public void setPositionValues(int index, float position) {
|
||||
})
|
||||
public void setPositionValues(int index, Dynamic position) {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (position != null && dynamicIsPercent(position)) {
|
||||
setPositionPercent(ViewProps.POSITION_SPACING_TYPES[index], getDynamicAsPercent(position));
|
||||
} else {
|
||||
setPosition(
|
||||
ViewProps.POSITION_SPACING_TYPES[index],
|
||||
YogaConstants.isUndefined(position) ? position : PixelUtil.toPixelFromDIP(position));
|
||||
position == null ? YogaConstants.UNDEFINED : getDynamicAsFloat(position));
|
||||
}
|
||||
|
||||
position.recycle();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.POSITION)
|
||||
|
|
|
@ -11,6 +11,7 @@ package com.facebook.react.uimanager;
|
|||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.facebook.yoga.YogaAlign;
|
||||
|
@ -23,6 +24,7 @@ import com.facebook.yoga.YogaMeasureFunction;
|
|||
import com.facebook.yoga.YogaNode;
|
||||
import com.facebook.yoga.YogaOverflow;
|
||||
import com.facebook.yoga.YogaPositionType;
|
||||
import com.facebook.yoga.YogaValue;
|
||||
import com.facebook.yoga.YogaWrap;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.uimanager.annotations.ReactPropertyHolder;
|
||||
|
@ -72,7 +74,8 @@ public class ReactShadowNode {
|
|||
private float mAbsoluteRight;
|
||||
private float mAbsoluteBottom;
|
||||
private final Spacing mDefaultPadding = new Spacing(0);
|
||||
private final Spacing mPadding = new Spacing(YogaConstants.UNDEFINED);
|
||||
private final float[] mPadding = new float[Spacing.ALL + 1];
|
||||
private final boolean[] mPaddingIsPercent = new boolean[Spacing.ALL + 1];
|
||||
private final YogaNode mYogaNode;
|
||||
|
||||
public ReactShadowNode() {
|
||||
|
@ -82,6 +85,7 @@ public class ReactShadowNode {
|
|||
node = new YogaNode();
|
||||
}
|
||||
mYogaNode = node;
|
||||
Arrays.fill(mPadding, YogaConstants.UNDEFINED);
|
||||
} else {
|
||||
mYogaNode = null;
|
||||
}
|
||||
|
@ -514,38 +518,62 @@ public class ReactShadowNode {
|
|||
mYogaNode.setDirection(direction);
|
||||
}
|
||||
|
||||
public final float getStyleWidth() {
|
||||
return mYogaNode.getWidth().value;
|
||||
public final YogaValue getStyleWidth() {
|
||||
return mYogaNode.getWidth();
|
||||
}
|
||||
|
||||
public void setStyleWidth(float widthPx) {
|
||||
mYogaNode.setWidth(widthPx);
|
||||
}
|
||||
|
||||
public void setStyleWidthPercent(float percent) {
|
||||
mYogaNode.setWidthPercent(percent);
|
||||
}
|
||||
|
||||
public void setStyleMinWidth(float widthPx) {
|
||||
mYogaNode.setMinWidth(widthPx);
|
||||
}
|
||||
|
||||
public void setStyleMinWidthPercent(float percent) {
|
||||
mYogaNode.setMinWidthPercent(percent);
|
||||
}
|
||||
|
||||
public void setStyleMaxWidth(float widthPx) {
|
||||
mYogaNode.setMaxWidth(widthPx);
|
||||
}
|
||||
|
||||
public final float getStyleHeight() {
|
||||
return mYogaNode.getHeight().value;
|
||||
public void setStyleMaxWidthPercent(float percent) {
|
||||
mYogaNode.setMaxWidthPercent(percent);
|
||||
}
|
||||
|
||||
public final YogaValue getStyleHeight() {
|
||||
return mYogaNode.getHeight();
|
||||
}
|
||||
|
||||
public void setStyleHeight(float heightPx) {
|
||||
mYogaNode.setHeight(heightPx);
|
||||
}
|
||||
|
||||
public void setStyleHeightPercent(float percent) {
|
||||
mYogaNode.setHeightPercent(percent);
|
||||
}
|
||||
|
||||
public void setStyleMinHeight(float widthPx) {
|
||||
mYogaNode.setMinHeight(widthPx);
|
||||
}
|
||||
|
||||
public void setStyleMinHeightPercent(float percent) {
|
||||
mYogaNode.setMinHeightPercent(percent);
|
||||
}
|
||||
|
||||
public void setStyleMaxHeight(float widthPx) {
|
||||
mYogaNode.setMaxHeight(widthPx);
|
||||
}
|
||||
|
||||
public void setStyleMaxHeightPercent(float percent) {
|
||||
mYogaNode.setMaxHeightPercent(percent);
|
||||
}
|
||||
|
||||
public void setFlex(float flex) {
|
||||
mYogaNode.setFlex(flex);
|
||||
}
|
||||
|
@ -562,6 +590,10 @@ public class ReactShadowNode {
|
|||
mYogaNode.setFlexBasis(flexBasis);
|
||||
}
|
||||
|
||||
public void setFlexBasisPercent(float percent) {
|
||||
mYogaNode.setFlexBasisPercent(percent);
|
||||
}
|
||||
|
||||
public void setStyleAspectRatio(float aspectRatio) {
|
||||
mYogaNode.setAspectRatio(aspectRatio);
|
||||
}
|
||||
|
@ -594,12 +626,16 @@ public class ReactShadowNode {
|
|||
mYogaNode.setMargin(YogaEdge.fromInt(spacingType), margin);
|
||||
}
|
||||
|
||||
public void setMarginPercent(int spacingType, float percent) {
|
||||
mYogaNode.setMarginPercent(YogaEdge.fromInt(spacingType), percent);
|
||||
}
|
||||
|
||||
public final float getPadding(int spacingType) {
|
||||
return mYogaNode.getLayoutPadding(YogaEdge.fromInt(spacingType));
|
||||
}
|
||||
|
||||
public final float getStylePadding(int spacingType) {
|
||||
return mYogaNode.getPadding(YogaEdge.fromInt(spacingType)).value;
|
||||
public final YogaValue getStylePadding(int spacingType) {
|
||||
return mYogaNode.getPadding(YogaEdge.fromInt(spacingType));
|
||||
}
|
||||
|
||||
public void setDefaultPadding(int spacingType, float padding) {
|
||||
|
@ -608,7 +644,14 @@ public class ReactShadowNode {
|
|||
}
|
||||
|
||||
public void setPadding(int spacingType, float padding) {
|
||||
mPadding.set(spacingType, padding);
|
||||
mPadding[spacingType] = padding;
|
||||
mPaddingIsPercent[spacingType] = false;
|
||||
updatePadding();
|
||||
}
|
||||
|
||||
public void setPaddingPercent(int spacingType, float percent) {
|
||||
mPadding[spacingType] = percent;
|
||||
mPaddingIsPercent[spacingType] = !YogaConstants.isUndefined(percent);
|
||||
updatePadding();
|
||||
}
|
||||
|
||||
|
@ -618,28 +661,31 @@ public class ReactShadowNode {
|
|||
spacingType == Spacing.RIGHT ||
|
||||
spacingType == Spacing.START ||
|
||||
spacingType == Spacing.END) {
|
||||
if (YogaConstants.isUndefined(mPadding.getRaw(spacingType)) &&
|
||||
YogaConstants.isUndefined(mPadding.getRaw(Spacing.HORIZONTAL)) &&
|
||||
YogaConstants.isUndefined(mPadding.getRaw(Spacing.ALL))) {
|
||||
if (YogaConstants.isUndefined(mPadding[spacingType]) &&
|
||||
YogaConstants.isUndefined(mPadding[Spacing.HORIZONTAL]) &&
|
||||
YogaConstants.isUndefined(mPadding[Spacing.ALL])) {
|
||||
mYogaNode.setPadding(YogaEdge.fromInt(spacingType), mDefaultPadding.getRaw(spacingType));
|
||||
} else {
|
||||
mYogaNode.setPadding(YogaEdge.fromInt(spacingType), mPadding.getRaw(spacingType));
|
||||
continue;
|
||||
}
|
||||
} else if (spacingType == Spacing.TOP || spacingType == Spacing.BOTTOM) {
|
||||
if (YogaConstants.isUndefined(mPadding.getRaw(spacingType)) &&
|
||||
YogaConstants.isUndefined(mPadding.getRaw(Spacing.VERTICAL)) &&
|
||||
YogaConstants.isUndefined(mPadding.getRaw(Spacing.ALL))) {
|
||||
if (YogaConstants.isUndefined(mPadding[spacingType]) &&
|
||||
YogaConstants.isUndefined(mPadding[Spacing.VERTICAL]) &&
|
||||
YogaConstants.isUndefined(mPadding[Spacing.ALL])) {
|
||||
mYogaNode.setPadding(YogaEdge.fromInt(spacingType), mDefaultPadding.getRaw(spacingType));
|
||||
} else {
|
||||
mYogaNode.setPadding(YogaEdge.fromInt(spacingType), mPadding.getRaw(spacingType));
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (YogaConstants.isUndefined(mPadding.getRaw(spacingType))) {
|
||||
if (YogaConstants.isUndefined(mPadding[spacingType])) {
|
||||
mYogaNode.setPadding(YogaEdge.fromInt(spacingType), mDefaultPadding.getRaw(spacingType));
|
||||
} else {
|
||||
mYogaNode.setPadding(YogaEdge.fromInt(spacingType), mPadding.getRaw(spacingType));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (mPaddingIsPercent[spacingType]) {
|
||||
mYogaNode.setPaddingPercent(YogaEdge.fromInt(spacingType), mPadding[spacingType]);
|
||||
} else {
|
||||
mYogaNode.setPadding(YogaEdge.fromInt(spacingType), mPadding[spacingType]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -651,6 +697,10 @@ public class ReactShadowNode {
|
|||
mYogaNode.setPosition(YogaEdge.fromInt(spacingType), position);
|
||||
}
|
||||
|
||||
public void setPositionPercent(int spacingType, float percent) {
|
||||
mYogaNode.setPositionPercent(YogaEdge.fromInt(spacingType), percent);
|
||||
}
|
||||
|
||||
public void setPositionType(YogaPositionType positionType) {
|
||||
mYogaNode.setPositionType(positionType);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,10 @@ import android.net.Uri;
|
|||
import com.facebook.common.util.UriUtil;
|
||||
import com.facebook.yoga.YogaConstants;
|
||||
import com.facebook.drawee.controller.AbstractDraweeControllerBuilder;
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableType;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.views.text.ReactTextInlineImageShadowNode;
|
||||
|
@ -74,13 +77,23 @@ public class FrescoBasedReactTextInlineImageShadowNode extends ReactTextInlineIm
|
|||
* Besides width/height, all other layout props on inline images are ignored
|
||||
*/
|
||||
@Override
|
||||
public void setWidth(float width) {
|
||||
mWidth = width;
|
||||
public void setWidth(Dynamic width) {
|
||||
if (width.getType() == ReadableType.Number) {
|
||||
mWidth = (float) width.asDouble();
|
||||
} else {
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Inline images must not have percentage based width");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeight(float height) {
|
||||
mHeight = height;
|
||||
public void setHeight(Dynamic height) {
|
||||
if (height.getType() == ReadableType.Number) {
|
||||
mHeight = (float) height.asDouble();
|
||||
} else {
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Inline images must not have percentage based height");
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable Uri getUri() {
|
||||
|
|
|
@ -19,7 +19,7 @@ public class YogaValue {
|
|||
public final float value;
|
||||
public final YogaUnit unit;
|
||||
|
||||
YogaValue(float value, YogaUnit unit) {
|
||||
public YogaValue(float value, YogaUnit unit) {
|
||||
this.value = value;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
|
|
@ -181,8 +181,6 @@ YGCalloc gYGCalloc = &calloc;
|
|||
YGRealloc gYGRealloc = &realloc;
|
||||
YGFree gYGFree = &free;
|
||||
|
||||
static YGValue YGValueUndefined = YG_UNDEFINED_VALUES;
|
||||
|
||||
static YGValue YGValueZero = {.value = 0, .unit = YGUnitPixel};
|
||||
|
||||
#ifdef ANDROID
|
||||
|
|
|
@ -43,6 +43,8 @@ typedef struct YGValue {
|
|||
YGUnit unit;
|
||||
} YGValue;
|
||||
|
||||
static const YGValue YGValueUndefined = { YGUndefined, YGUnitUndefined };
|
||||
|
||||
typedef struct YGNode *YGNodeRef;
|
||||
typedef YGSize (*YGMeasureFunc)(YGNodeRef node,
|
||||
float width,
|
||||
|
|
Loading…
Reference in New Issue