react-native/React/Views/RCTLayout.m
Valentin Shergin f91f7d91a1 Reimagining of RCTShadowView layout API
Summary:
This is reimagining of interoperability layer between Yoga and ShadowViews (at least in Yoga -> RN part).
Goals:
 * Make it clear and easy.
 * Make clear separation between "what layout what", now parent always layout children, noone layout itself.
 * Make possible to interleave Yoga layout with custom imperative layout (may be used in SafeAreaView, Text, Modal, InputAccessoryView and so on).

Reviewed By: mmmulani

Differential Revision: D6863654

fbshipit-source-id: 5a6a933874f121d46f744aab99a31ae42ddd4a1b
2018-02-12 00:32:43 -08:00

146 lines
4.4 KiB
Objective-C

/**
* Copyright (c) 2015-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.
*/
#import <yoga/Yoga.h>
#import "RCTAssert.h"
#import "RCTShadowView+Layout.h"
RCTLayoutMetrics RCTLayoutMetricsFromYogaNode(YGNodeRef yogaNode)
{
RCTLayoutMetrics layoutMetrics;
CGRect frame = (CGRect){
(CGPoint){
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetLeft(yogaNode)),
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetTop(yogaNode))
},
(CGSize){
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetWidth(yogaNode)),
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetHeight(yogaNode))
}
};
UIEdgeInsets padding = (UIEdgeInsets){
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeTop)),
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeLeft)),
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeBottom)),
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeRight))
};
UIEdgeInsets borderWidth = (UIEdgeInsets){
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeTop)),
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft)),
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeBottom)),
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeRight))
};
UIEdgeInsets compoundInsets = (UIEdgeInsets){
borderWidth.top + padding.top,
borderWidth.left + padding.left,
borderWidth.bottom + padding.bottom,
borderWidth.right + padding.right
};
CGRect bounds = (CGRect){CGPointZero, frame.size};
CGRect contentFrame = UIEdgeInsetsInsetRect(bounds, compoundInsets);
layoutMetrics.frame = frame;
layoutMetrics.borderWidth = borderWidth;
layoutMetrics.contentFrame = contentFrame;
layoutMetrics.displayType = RCTReactDisplayTypeFromYogaDisplayType(YGNodeStyleGetDisplay(yogaNode));
layoutMetrics.layoutDirection = RCTUIKitLayoutDirectionFromYogaLayoutDirection(YGNodeLayoutGetDirection(yogaNode));
return layoutMetrics;
}
/**
* Yoga and CoreGraphics have different opinions about how "infinity" value
* should be represented.
* Yoga uses `NAN` which requires additional effort to compare all those values,
* whereas GoreGraphics uses `GFLOAT_MAX` which can be easyly compared with
* standard `==` operator.
*/
float RCTYogaFloatFromCoreGraphicsFloat(CGFloat value)
{
if (value == CGFLOAT_MAX || isnan(value) || isinf(value)) {
return YGUndefined;
}
return value;
}
CGFloat RCTCoreGraphicsFloatFromYogaFloat(float value)
{
if (value == YGUndefined || isnan(value) || isinf(value)) {
return CGFLOAT_MAX;
}
return value;
}
CGFloat RCTCoreGraphicsFloatFromYogaValue(YGValue value, CGFloat baseFloatValue)
{
switch (value.unit) {
case YGUnitPoint:
return RCTCoreGraphicsFloatFromYogaFloat(value.value);
case YGUnitPercent:
return RCTCoreGraphicsFloatFromYogaFloat(value.value) * baseFloatValue;
case YGUnitAuto:
case YGUnitUndefined:
return baseFloatValue;
}
}
YGDirection RCTYogaLayoutDirectionFromUIKitLayoutDirection(UIUserInterfaceLayoutDirection direction)
{
switch (direction) {
case UIUserInterfaceLayoutDirectionRightToLeft:
return YGDirectionRTL;
case UIUserInterfaceLayoutDirectionLeftToRight:
return YGDirectionLTR;
}
}
UIUserInterfaceLayoutDirection RCTUIKitLayoutDirectionFromYogaLayoutDirection(YGDirection direction)
{
switch (direction) {
case YGDirectionInherit:
case YGDirectionLTR:
return UIUserInterfaceLayoutDirectionLeftToRight;
case YGDirectionRTL:
return UIUserInterfaceLayoutDirectionRightToLeft;
}
}
YGDisplay RCTYogaDisplayTypeFromReactDisplayType(RCTDisplayType displayType)
{
switch (displayType) {
case RCTDisplayTypeNone:
return YGDisplayNone;
case RCTDisplayTypeFlex:
return YGDisplayFlex;
case RCTDisplayTypeInline:
RCTAssert(NO, @"RCTDisplayTypeInline cannot be converted to YGDisplay value.");
return YGDisplayNone;
}
}
RCTDisplayType RCTReactDisplayTypeFromYogaDisplayType(YGDisplay displayType)
{
switch (displayType) {
case YGDisplayFlex:
return RCTDisplayTypeFlex;
case YGDisplayNone:
return RCTDisplayTypeNone;
}
}