WIP: Improve the Objective-C and Swift bridge #289
3
.gitignore
vendored
3
.gitignore
vendored
@@ -8,3 +8,6 @@
|
|||||||
|
|
||||||
# Visual studio code
|
# Visual studio code
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
# Xcode
|
||||||
|
xcuserdata
|
@@ -1,77 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
#import <yoga/Yoga.h>
|
|
||||||
|
|
||||||
@interface UIView (Yoga)
|
|
||||||
|
|
||||||
/**
|
|
||||||
The property that decides if we should include this view when calculating layout. Defaults to YES.
|
|
||||||
*/
|
|
||||||
@property (nonatomic, readwrite, assign, setter=yg_setIncludeInLayout:) BOOL yg_includeInLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
The property that decides during layout/sizing whether or not yg_* properties should be applied. Defaults to NO.
|
|
||||||
*/
|
|
||||||
@property (nonatomic, readwrite, assign, setter=yg_setUsesYoga:) BOOL yg_usesYoga;
|
|
||||||
|
|
||||||
- (void)yg_setDirection:(YGDirection)direction;
|
|
||||||
- (void)yg_setFlexDirection:(YGFlexDirection)flexDirection;
|
|
||||||
- (void)yg_setJustifyContent:(YGJustify)justifyContent;
|
|
||||||
- (void)yg_setAlignContent:(YGAlign)alignContent;
|
|
||||||
- (void)yg_setAlignItems:(YGAlign)alignItems;
|
|
||||||
- (void)yg_setAlignSelf:(YGAlign)alignSelf;
|
|
||||||
- (void)yg_setPositionType:(YGPositionType)positionType;
|
|
||||||
- (void)yg_setFlexWrap:(YGWrap)flexWrap;
|
|
||||||
|
|
||||||
- (void)yg_setFlexGrow:(CGFloat)flexGrow;
|
|
||||||
- (void)yg_setFlexShrink:(CGFloat)flexShrink;
|
|
||||||
- (void)yg_setFlexBasis:(CGFloat)flexBasis;
|
|
||||||
|
|
||||||
- (void)yg_setPosition:(CGFloat)position forEdge:(YGEdge)edge;
|
|
||||||
- (void)yg_setMargin:(CGFloat)margin forEdge:(YGEdge)edge;
|
|
||||||
- (void)yg_setPadding:(CGFloat)padding forEdge:(YGEdge)edge;
|
|
||||||
|
|
||||||
- (void)yg_setWidth:(CGFloat)width;
|
|
||||||
- (void)yg_setHeight:(CGFloat)height;
|
|
||||||
- (void)yg_setMinWidth:(CGFloat)minWidth;
|
|
||||||
- (void)yg_setMinHeight:(CGFloat)minHeight;
|
|
||||||
- (void)yg_setMaxWidth:(CGFloat)maxWidth;
|
|
||||||
- (void)yg_setMaxHeight:(CGFloat)maxHeight;
|
|
||||||
|
|
||||||
// Yoga specific properties, not compatible with flexbox specification
|
|
||||||
- (void)yg_setAspectRatio:(CGFloat)aspectRatio;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get the resolved direction of this node. This won't be YGDirectionInherit
|
|
||||||
*/
|
|
||||||
- (YGDirection)yg_resolvedDirection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Perform a layout calculation and update the frames of the views in the hierarchy with the results
|
|
||||||
*/
|
|
||||||
- (void)yg_applyLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the size of the view if no constraints were given. This could equivalent to calling [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
|
||||||
*/
|
|
||||||
- (CGSize)yg_intrinsicSize;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the number of children that are using Flexbox.
|
|
||||||
*/
|
|
||||||
- (NSUInteger)yg_numberOfChildren;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Return a BOOL indiciating whether or not we this node contains any subviews that are included in Yoga's layout.
|
|
||||||
*/
|
|
||||||
- (BOOL)yg_isLeaf;
|
|
||||||
|
|
||||||
@end
|
|
@@ -1,397 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import "UIView+Yoga.h"
|
|
||||||
|
|
||||||
#import <objc/runtime.h>
|
|
||||||
|
|
||||||
@interface YGNodeBridge : NSObject
|
|
||||||
@property (nonatomic, assign, readonly) YGNodeRef cnode;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation YGNodeBridge
|
|
||||||
|
|
||||||
+ (void)initialize
|
|
||||||
{
|
|
||||||
YGSetExperimentalFeatureEnabled(YGExperimentalFeatureWebFlexBasis, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype)init
|
|
||||||
{
|
|
||||||
if ([super init]) {
|
|
||||||
_cnode = YGNodeNew();
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc
|
|
||||||
{
|
|
||||||
YGNodeFree(_cnode);
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation UIView (Yoga)
|
|
||||||
|
|
||||||
- (BOOL)yg_usesYoga
|
|
||||||
{
|
|
||||||
NSNumber *usesYoga = objc_getAssociatedObject(self, @selector(yg_usesYoga));
|
|
||||||
return [usesYoga boolValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)yg_includeInLayout
|
|
||||||
{
|
|
||||||
NSNumber *includeInLayout = objc_getAssociatedObject(self, @selector(yg_includeInLayout));
|
|
||||||
return (includeInLayout != nil) ? [includeInLayout boolValue] : YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSUInteger)yg_numberOfChildren
|
|
||||||
{
|
|
||||||
return YGNodeGetChildCount([self ygNode]);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)yg_isLeaf
|
|
||||||
{
|
|
||||||
NSAssert([NSThread isMainThread], @"This method must be called on the main thread.");
|
|
||||||
if ([self yg_usesYoga]) {
|
|
||||||
for (UIView *subview in self.subviews) {
|
|
||||||
if ([subview yg_usesYoga] && [subview yg_includeInLayout]) {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Setters
|
|
||||||
|
|
||||||
- (void)yg_setIncludeInLayout:(BOOL)includeInLayout
|
|
||||||
{
|
|
||||||
objc_setAssociatedObject(
|
|
||||||
self,
|
|
||||||
@selector(yg_includeInLayout),
|
|
||||||
@(includeInLayout),
|
|
||||||
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setUsesYoga:(BOOL)enabled
|
|
||||||
{
|
|
||||||
objc_setAssociatedObject(
|
|
||||||
self,
|
|
||||||
@selector(yg_usesYoga),
|
|
||||||
@(enabled),
|
|
||||||
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setDirection:(YGDirection)direction
|
|
||||||
{
|
|
||||||
YGNodeStyleSetDirection([self ygNode], direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setFlexDirection:(YGFlexDirection)flexDirection
|
|
||||||
{
|
|
||||||
YGNodeStyleSetFlexDirection([self ygNode], flexDirection);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setJustifyContent:(YGJustify)justifyContent
|
|
||||||
{
|
|
||||||
YGNodeStyleSetJustifyContent([self ygNode], justifyContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setAlignContent:(YGAlign)alignContent
|
|
||||||
{
|
|
||||||
YGNodeStyleSetAlignContent([self ygNode], alignContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setAlignItems:(YGAlign)alignItems
|
|
||||||
{
|
|
||||||
YGNodeStyleSetAlignItems([self ygNode], alignItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setAlignSelf:(YGAlign)alignSelf
|
|
||||||
{
|
|
||||||
YGNodeStyleSetAlignSelf([self ygNode], alignSelf);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setPositionType:(YGPositionType)positionType
|
|
||||||
{
|
|
||||||
YGNodeStyleSetPositionType([self ygNode], positionType);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setFlexWrap:(YGWrap)flexWrap
|
|
||||||
{
|
|
||||||
YGNodeStyleSetFlexWrap([self ygNode], flexWrap);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setFlexGrow:(CGFloat)flexGrow
|
|
||||||
{
|
|
||||||
YGNodeStyleSetFlexGrow([self ygNode], flexGrow);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setFlexShrink:(CGFloat)flexShrink
|
|
||||||
{
|
|
||||||
YGNodeStyleSetFlexShrink([self ygNode], flexShrink);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setFlexBasis:(CGFloat)flexBasis
|
|
||||||
{
|
|
||||||
YGNodeStyleSetFlexBasis([self ygNode], flexBasis);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setPosition:(CGFloat)position forEdge:(YGEdge)edge
|
|
||||||
{
|
|
||||||
YGNodeStyleSetPosition([self ygNode], edge, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setMargin:(CGFloat)margin forEdge:(YGEdge)edge
|
|
||||||
{
|
|
||||||
YGNodeStyleSetMargin([self ygNode], edge, margin);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setPadding:(CGFloat)padding forEdge:(YGEdge)edge
|
|
||||||
{
|
|
||||||
YGNodeStyleSetPadding([self ygNode], edge, padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setWidth:(CGFloat)width
|
|
||||||
{
|
|
||||||
YGNodeStyleSetWidth([self ygNode], width);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setHeight:(CGFloat)height
|
|
||||||
{
|
|
||||||
YGNodeStyleSetHeight([self ygNode], height);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setMinWidth:(CGFloat)minWidth
|
|
||||||
{
|
|
||||||
YGNodeStyleSetMinWidth([self ygNode], minWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setMinHeight:(CGFloat)minHeight
|
|
||||||
{
|
|
||||||
YGNodeStyleSetMinHeight([self ygNode], minHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setMaxWidth:(CGFloat)maxWidth
|
|
||||||
{
|
|
||||||
YGNodeStyleSetMaxWidth([self ygNode], maxWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setMaxHeight:(CGFloat)maxHeight
|
|
||||||
{
|
|
||||||
YGNodeStyleSetMaxHeight([self ygNode], maxHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setAspectRatio:(CGFloat)aspectRatio
|
|
||||||
{
|
|
||||||
YGNodeStyleSetAspectRatio([self ygNode], aspectRatio);
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Layout and Sizing
|
|
||||||
|
|
||||||
- (YGDirection)yg_resolvedDirection
|
|
||||||
{
|
|
||||||
return YGNodeLayoutGetDirection([self ygNode]);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_applyLayout
|
|
||||||
{
|
|
||||||
[self calculateLayoutWithSize:self.bounds.size];
|
|
||||||
YGApplyLayoutToViewHierarchy(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGSize)yg_intrinsicSize
|
|
||||||
{
|
|
||||||
const CGSize constrainedSize = {
|
|
||||||
.width = YGUndefined,
|
|
||||||
.height = YGUndefined,
|
|
||||||
};
|
|
||||||
return [self calculateLayoutWithSize:constrainedSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Private
|
|
||||||
|
|
||||||
- (YGNodeRef)ygNode
|
|
||||||
{
|
|
||||||
YGNodeBridge *node = objc_getAssociatedObject(self, @selector(ygNode));
|
|
||||||
if (!node) {
|
|
||||||
node = [YGNodeBridge new];
|
|
||||||
YGNodeSetContext(node.cnode, (__bridge void *) self);
|
|
||||||
objc_setAssociatedObject(self, @selector(ygNode), node, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node.cnode;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGSize)calculateLayoutWithSize:(CGSize)size
|
|
||||||
{
|
|
||||||
NSAssert([NSThread isMainThread], @"YG Layout calculation must be done on main.");
|
|
||||||
NSAssert([self yg_usesYoga], @"YG Layout is not enabled for this view.");
|
|
||||||
|
|
||||||
YGAttachNodesFromViewHierachy(self);
|
|
||||||
|
|
||||||
const YGNodeRef node = [self ygNode];
|
|
||||||
YGNodeCalculateLayout(
|
|
||||||
node,
|
|
||||||
size.width,
|
|
||||||
size.height,
|
|
||||||
YGNodeStyleGetDirection(node));
|
|
||||||
|
|
||||||
return (CGSize) {
|
|
||||||
.width = YGNodeLayoutGetWidth(node),
|
|
||||||
.height = YGNodeLayoutGetHeight(node),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static YGSize YGMeasureView(
|
|
||||||
YGNodeRef node,
|
|
||||||
float width,
|
|
||||||
YGMeasureMode widthMode,
|
|
||||||
float height,
|
|
||||||
YGMeasureMode heightMode)
|
|
||||||
{
|
|
||||||
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
|
|
||||||
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height;
|
|
||||||
|
|
||||||
UIView *view = (__bridge UIView*) YGNodeGetContext(node);
|
|
||||||
const CGSize sizeThatFits = [view sizeThatFits:(CGSize) {
|
|
||||||
.width = constrainedWidth,
|
|
||||||
.height = constrainedHeight,
|
|
||||||
}];
|
|
||||||
|
|
||||||
return (YGSize) {
|
|
||||||
.width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode),
|
|
||||||
.height = YGSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static CGFloat YGSanitizeMeasurement(
|
|
||||||
CGFloat constrainedSize,
|
|
||||||
CGFloat measuredSize,
|
|
||||||
YGMeasureMode measureMode)
|
|
||||||
{
|
|
||||||
CGFloat result;
|
|
||||||
if (measureMode == YGMeasureModeExactly) {
|
|
||||||
result = constrainedSize;
|
|
||||||
} else if (measureMode == YGMeasureModeAtMost) {
|
|
||||||
result = MIN(constrainedSize, measuredSize);
|
|
||||||
} else {
|
|
||||||
result = measuredSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL YGNodeHasExactSameChildren(const YGNodeRef node, NSArray<UIView *> *subviews)
|
|
||||||
{
|
|
||||||
if (YGNodeGetChildCount(node) != subviews.count) {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<subviews.count; i++) {
|
|
||||||
if (YGNodeGetChild(node, i) != subviews[i].ygNode) {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void YGAttachNodesFromViewHierachy(UIView *const view)
|
|
||||||
{
|
|
||||||
const YGNodeRef node = [view ygNode];
|
|
||||||
|
|
||||||
// Only leaf nodes should have a measure function
|
|
||||||
if (view.yg_isLeaf) {
|
|
||||||
YGNodeSetMeasureFunc(node, YGMeasureView);
|
|
||||||
YGRemoveAllChildren(node);
|
|
||||||
} else {
|
|
||||||
YGNodeSetMeasureFunc(node, NULL);
|
|
||||||
|
|
||||||
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
|
|
||||||
for (UIView *subview in view.subviews) {
|
|
||||||
if ([subview yg_includeInLayout]) {
|
|
||||||
[subviewsToInclude addObject:subview];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!YGNodeHasExactSameChildren(node, subviewsToInclude)) {
|
|
||||||
YGRemoveAllChildren(node);
|
|
||||||
for (int i=0; i<subviewsToInclude.count; i++) {
|
|
||||||
YGNodeInsertChild(node, [subviewsToInclude[i] ygNode], i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (UIView *const subview in subviewsToInclude) {
|
|
||||||
YGAttachNodesFromViewHierachy(subview);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void YGRemoveAllChildren(const YGNodeRef node)
|
|
||||||
{
|
|
||||||
if (node == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (YGNodeGetChildCount(node) > 0) {
|
|
||||||
YGNodeRemoveChild(node, YGNodeGetChild(node, YGNodeGetChildCount(node) - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static CGFloat YGRoundPixelValue(CGFloat value)
|
|
||||||
{
|
|
||||||
static CGFloat scale;
|
|
||||||
static dispatch_once_t onceToken;
|
|
||||||
dispatch_once(&onceToken, ^(){
|
|
||||||
scale = [UIScreen mainScreen].scale;
|
|
||||||
});
|
|
||||||
|
|
||||||
return round(value * scale) / scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void YGApplyLayoutToViewHierarchy(UIView *view)
|
|
||||||
{
|
|
||||||
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread.");
|
|
||||||
if (![view yg_includeInLayout]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
YGNodeRef node = [view ygNode];
|
|
||||||
const CGPoint topLeft = {
|
|
||||||
YGNodeLayoutGetLeft(node),
|
|
||||||
YGNodeLayoutGetTop(node),
|
|
||||||
};
|
|
||||||
|
|
||||||
const CGPoint bottomRight = {
|
|
||||||
topLeft.x + YGNodeLayoutGetWidth(node),
|
|
||||||
topLeft.y + YGNodeLayoutGetHeight(node),
|
|
||||||
};
|
|
||||||
|
|
||||||
view.frame = (CGRect) {
|
|
||||||
.origin = {
|
|
||||||
.x = YGRoundPixelValue(topLeft.x),
|
|
||||||
.y = YGRoundPixelValue(topLeft.y),
|
|
||||||
},
|
|
||||||
.size = {
|
|
||||||
.width = YGRoundPixelValue(bottomRight.x) - YGRoundPixelValue(topLeft.x),
|
|
||||||
.height = YGRoundPixelValue(bottomRight.y) - YGRoundPixelValue(topLeft.y),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!view.yg_isLeaf) {
|
|
||||||
for (NSUInteger i=0; i<view.subviews.count; i++) {
|
|
||||||
YGApplyLayoutToViewHierarchy(view.subviews[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
17
YogaKit/UIView+YogaKit.h
Normal file
17
YogaKit/UIView+YogaKit.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import <YogaKit/YKLayout.h>
|
||||||
|
|
||||||
|
@interface UIView (YogaKit)
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) YKLayout* layout;
|
||||||
|
|
||||||
|
@end
|
28
YogaKit/UIView+YogaKit.m
Normal file
28
YogaKit/UIView+YogaKit.m
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <YogaKit/UIView+YogaKit.h>
|
||||||
|
#import <YogaKit/YKLayout+Private.h>
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
@implementation UIView (YogaKit)
|
||||||
|
|
||||||
|
- (YKLayout *)layout
|
||||||
|
{
|
||||||
|
YKLayout *layout = objc_getAssociatedObject(self, @selector(layout));
|
||||||
|
if (!layout) {
|
||||||
|
layout = [[YKLayout alloc] initWithView:self];
|
||||||
|
objc_setAssociatedObject(self, @selector(layout), layout, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
48
YogaKit/YKEnums.h
Normal file
48
YogaKit/YKEnums.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, YKFlexDirection) {
|
||||||
|
YKFlexDirectionColumn,
|
||||||
|
YKFlexDirectionColumnReverse,
|
||||||
|
YKFlexDirectionRow,
|
||||||
|
YKFlexDirectionRowReverse,
|
||||||
|
} NS_SWIFT_NAME(FlexDirection);
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, YKPositionType) {
|
||||||
|
YKPositionTypeRelative,
|
||||||
|
YKPositionTypeAbsolute,
|
||||||
|
} NS_SWIFT_NAME(PositionType);
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, YKJustify) {
|
||||||
|
YKJustifyFlexStart,
|
||||||
|
YKJustifyCenter,
|
||||||
|
YKJustifyFlexEnd,
|
||||||
|
YKJustifySpaceBetween,
|
||||||
|
YKJustifySpaceAround,
|
||||||
|
} NS_SWIFT_NAME(Justify);
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, YKDirection) {
|
||||||
|
YKDirectionInherit,
|
||||||
|
YKDirectionLeftToRight,
|
||||||
|
YKDirectionRightToLeft,
|
||||||
|
} NS_SWIFT_NAME(Direction);
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, YKWrap) {
|
||||||
|
YKWrapNoWrap,
|
||||||
|
YKWrapWrap,
|
||||||
|
} NS_SWIFT_NAME(Wrap);
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, YKAlign) {
|
||||||
|
YKAlignAuto,
|
||||||
|
YKAlignFlexStart,
|
||||||
|
YKAlignCenter,
|
||||||
|
YKAlignFlexEnd,
|
||||||
|
YKAlignStretch,
|
||||||
|
} NS_SWIFT_NAME(Align);
|
||||||
|
|
16
YogaKit/YKLayout+Private.h
Normal file
16
YogaKit/YKLayout+Private.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <YogaKit/YKLayout.h>
|
||||||
|
|
||||||
|
@interface YKLayout ()
|
||||||
|
|
||||||
|
- (instancetype)initWithView:(UIView*)view;
|
||||||
|
|
||||||
|
@end
|
97
YogaKit/YKLayout.h
Normal file
97
YogaKit/YKLayout.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "YKEnums.h"
|
||||||
|
|
||||||
|
@interface YKLayout : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
The property that decides if we should include this view when calculating layout. Defaults to YES.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, setter=setIncluded:) BOOL isIncluded;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The property that decides during layout/sizing whether or not yk_* properties should be applied. Defaults to NO.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, setter=setEnabled:) BOOL isEnabled;
|
||||||
|
|
||||||
|
@property (nonatomic) YKDirection direction;
|
||||||
|
@property (nonatomic) YKFlexDirection flexDirection;
|
||||||
|
@property (nonatomic) YKJustify justifyContent;
|
||||||
|
@property (nonatomic) YKAlign alignContent;
|
||||||
|
@property (nonatomic) YKAlign alignItems;
|
||||||
|
@property (nonatomic) YKAlign alignSelf;
|
||||||
|
@property (nonatomic) YKPositionType positionType;
|
||||||
|
@property (nonatomic) YKWrap flexWrap;
|
||||||
|
|
||||||
|
@property (nonatomic) CGFloat flexGrow;
|
||||||
|
@property (nonatomic) CGFloat flexShrink;
|
||||||
|
@property (nonatomic) CGFloat flexBasis;
|
||||||
|
|
||||||
|
@property (nonatomic) CGFloat positionLeft;
|
||||||
|
@property (nonatomic) CGFloat positionTop;
|
||||||
|
@property (nonatomic) CGFloat positionRight;
|
||||||
|
@property (nonatomic) CGFloat positionBottom;
|
||||||
|
@property (nonatomic) CGFloat positionStart;
|
||||||
|
@property (nonatomic) CGFloat positionEnd;
|
||||||
|
@property (nonatomic) CGFloat positionHorizontal;
|
||||||
|
|||||||
|
@property (nonatomic) CGFloat positionVertical;
|
||||||
|
@property (nonatomic) CGFloat positionAll;
|
||||||
|
|
||||||
|
@property (nonatomic) CGFloat marginLeft;
|
||||||
|
@property (nonatomic) CGFloat marginTop;
|
||||||
|
@property (nonatomic) CGFloat marginRight;
|
||||||
|
@property (nonatomic) CGFloat marginBottom;
|
||||||
|
@property (nonatomic) CGFloat marginStart;
|
||||||
|
@property (nonatomic) CGFloat marginEnd;
|
||||||
|
@property (nonatomic) CGFloat marginHorizontal;
|
||||||
|
@property (nonatomic) CGFloat marginVertical;
|
||||||
|
@property (nonatomic) CGFloat marginAll;
|
||||||
|
|
||||||
|
@property (nonatomic) CGFloat paddingLeft;
|
||||||
|
@property (nonatomic) CGFloat paddingTop;
|
||||||
|
@property (nonatomic) CGFloat paddingRight;
|
||||||
|
@property (nonatomic) CGFloat paddingBottom;
|
||||||
|
@property (nonatomic) CGFloat paddingStart;
|
||||||
![]() nit across the board, can we explicity add all the properties? i.e.
nit across the board, can we explicity add all the properties? i.e.
```
@property (nonatomic, readwrite, assign) ...
```
![]() Sure! Sure!
|
|||||||
|
@property (nonatomic) CGFloat paddingEnd;
|
||||||
|
@property (nonatomic) CGFloat paddingHorizontal;
|
||||||
|
@property (nonatomic) CGFloat paddingVertical;
|
||||||
|
@property (nonatomic) CGFloat paddingAll;
|
||||||
|
|
||||||
|
@property (nonatomic) CGFloat width;
|
||||||
|
@property (nonatomic) CGFloat height;
|
||||||
|
@property (nonatomic) CGFloat minWidth;
|
||||||
|
@property (nonatomic) CGFloat minHeight;
|
||||||
|
@property (nonatomic) CGFloat maxWidth;
|
||||||
|
@property (nonatomic) CGFloat maxHeight;
|
||||||
|
|
||||||
|
// Yoga specific properties, not compatible with flexbox specification
|
||||||
|
@property (nonatomic) CGFloat aspectRatio;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the resolved direction of this node. This won't be YGDirectionInherit
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly) YKDirection resolvedDirection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Perform a layout calculation and update the frames of the views in the hierarchy with the results
|
||||||
|
*/
|
||||||
|
- (void)apply;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the size of the view if no constraints were given. This could equivalent to calling [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly) CGSize intrinsicSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the number of children that are using Flexbox.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly) NSUInteger numberOfChildren;
|
||||||
|
|
||||||
|
@end
|
294
YogaKit/YKLayout.m
Normal file
294
YogaKit/YKLayout.m
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import <YogaKit/UIView+YogaKit.h>
|
||||||
|
#import <YogaKit/YKLayout.h>
|
||||||
|
#import <YogaKit/yoga.h>
|
||||||
|
|
||||||
|
#define YK_STYLE_PROPERTY_IMPL(objc_type, c_type, lowercased_name, capitalized_name) \
|
||||||
|
- (objc_type)lowercased_name \
|
||||||
|
{ \
|
||||||
|
return (objc_type)YGNodeStyleGet##capitalized_name(_node); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
- (void)set##capitalized_name:(objc_type)lowercased_name \
|
||||||
|
{ \
|
||||||
|
YGNodeStyleSet##capitalized_name(_node, (c_type)lowercased_name); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, edge) \
|
||||||
|
- (CGFloat)lowercased_name##edge \
|
||||||
|
{ \
|
||||||
|
return YGNodeStyleGet##capitalized_name(_node, YGEdge##edge); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
- (void)set##capitalized_name##edge:(CGFloat)lowercased_name##edge \
|
||||||
|
{ \
|
||||||
|
YGNodeStyleSet##capitalized_name(_node, YGEdge##edge, lowercased_name##edge); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name) \
|
||||||
|
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Left) \
|
||||||
|
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Top) \
|
||||||
|
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Right) \
|
||||||
|
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Bottom) \
|
||||||
|
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Start) \
|
||||||
|
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, End) \
|
||||||
|
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Horizontal) \
|
||||||
|
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Vertical) \
|
||||||
|
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, All)
|
||||||
|
|
||||||
|
@interface YKLayout ()
|
||||||
|
@property (nonatomic, weak, readonly) UIView* view;
|
||||||
|
@property (nonatomic, assign, readonly) YGNodeRef node;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation YKLayout
|
||||||
|
|
||||||
|
@synthesize isEnabled=_isEnabled;
|
||||||
|
@synthesize isIncluded=_isIncluded;
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
YGSetExperimentalFeatureEnabled(YGExperimentalFeatureWebFlexBasis, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithView:(UIView*)view
|
||||||
|
{
|
||||||
|
if ([super init]) {
|
||||||
|
_view = view;
|
||||||
|
_node = YGNodeNew();
|
||||||
|
YGNodeSetContext(_node, (__bridge void *) view);
|
||||||
|
_isEnabled = NO;
|
||||||
|
_isIncluded = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
YGNodeFree(_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)numberOfChildren
|
||||||
|
{
|
||||||
|
return YGNodeGetChildCount(_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
YK_STYLE_PROPERTY_IMPL(YKDirection, YGDirection, direction, Direction)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(YKFlexDirection, YGFlexDirection, flexDirection, FlexDirection)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(YKJustify, YGJustify, justifyContent, JustifyContent)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(YKAlign, YGAlign, alignContent, AlignContent)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(YKAlign, YGAlign, alignItems, AlignItems)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(YKAlign, YGAlign, alignSelf, AlignSelf)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(YKPositionType, YGPositionType, positionType, PositionType)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(YKWrap, YGWrap, flexWrap, FlexWrap)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, flexGrow, FlexGrow)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, flexShrink, FlexShrink)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, flexBasis, FlexBasis)
|
||||||
|
YK_STYLE_EDGE_PROPERTY_IMPL(position, Position)
|
||||||
|
YK_STYLE_EDGE_PROPERTY_IMPL(margin, Margin)
|
||||||
|
YK_STYLE_EDGE_PROPERTY_IMPL(padding, Padding)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, width, Width)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, height, Height)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, minWidth, MinWidth)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, minHeight, MinHeight)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, maxWidth, MaxWidth)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, maxHeight, MaxHeight)
|
||||||
|
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, aspectRatio, AspectRatio)
|
||||||
|
|
||||||
|
#pragma mark - Layout and Sizing
|
||||||
|
|
||||||
|
- (YKDirection)resolvedDirection
|
||||||
|
{
|
||||||
|
return (YKDirection)YGNodeLayoutGetDirection(_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)apply
|
||||||
|
{
|
||||||
|
[self calculateLayoutWithSize:self.view.bounds.size];
|
||||||
|
YKApplyLayoutToViewHierarchy(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)intrinsicSize
|
||||||
|
{
|
||||||
|
const CGSize constrainedSize = {
|
||||||
|
.width = YGUndefined,
|
||||||
|
.height = YGUndefined,
|
||||||
|
};
|
||||||
|
return [self calculateLayoutWithSize:constrainedSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Private
|
||||||
|
|
||||||
|
- (CGSize)calculateLayoutWithSize:(CGSize)size
|
||||||
|
{
|
||||||
|
NSAssert([NSThread isMainThread], @"YG Layout calculation must be done on main.");
|
||||||
|
NSAssert([self isEnabled], @"YG Layout is not enabled for this view.");
|
||||||
|
|
||||||
|
YKAttachNodesFromViewHierachy(self);
|
||||||
|
|
||||||
|
const YGNodeRef node = _node;
|
||||||
|
YGNodeCalculateLayout(
|
||||||
|
node,
|
||||||
|
size.width,
|
||||||
|
size.height,
|
||||||
|
YGNodeStyleGetDirection(node));
|
||||||
|
|
||||||
|
return (CGSize) {
|
||||||
|
.width = YGNodeLayoutGetWidth(node),
|
||||||
|
.height = YGNodeLayoutGetHeight(node),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static YGSize YKMeasureView(
|
||||||
|
YGNodeRef node,
|
||||||
|
float width,
|
||||||
|
YGMeasureMode widthMode,
|
||||||
|
float height,
|
||||||
|
YGMeasureMode heightMode)
|
||||||
|
{
|
||||||
|
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
|
||||||
|
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height;
|
||||||
|
|
||||||
|
UIView *view = (__bridge UIView*) YGNodeGetContext(node);
|
||||||
|
const CGSize sizeThatFits = [view sizeThatFits:(CGSize) {
|
||||||
|
.width = constrainedWidth,
|
||||||
|
.height = constrainedHeight,
|
||||||
|
}];
|
||||||
|
|
||||||
|
return (YGSize) {
|
||||||
|
.width = YKSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode),
|
||||||
|
.height = YKSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static CGFloat YKSanitizeMeasurement(
|
||||||
|
CGFloat constrainedSize,
|
||||||
|
CGFloat measuredSize,
|
||||||
|
YGMeasureMode measureMode)
|
||||||
|
{
|
||||||
|
CGFloat result;
|
||||||
|
if (measureMode == YGMeasureModeExactly) {
|
||||||
|
result = constrainedSize;
|
||||||
|
} else if (measureMode == YGMeasureModeAtMost) {
|
||||||
|
result = MIN(constrainedSize, measuredSize);
|
||||||
|
} else {
|
||||||
|
result = measuredSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void YKAttachNodesFromViewHierachy(YKLayout *layout) {
|
||||||
|
YGNodeRef node = layout.node;
|
||||||
|
UIView *view = layout.view;
|
||||||
|
|
||||||
|
// Only leaf nodes should have a measure function
|
||||||
|
if (![layout isEnabled] || view.subviews.count == 0) {
|
||||||
|
YGNodeSetMeasureFunc(node, YKMeasureView);
|
||||||
|
YKRemoveAllChildren(node);
|
||||||
|
} else {
|
||||||
|
YGNodeSetMeasureFunc(node, NULL);
|
||||||
|
|
||||||
|
// Create a list of all the subviews that we are going to use for layout.
|
||||||
|
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
|
||||||
|
for (UIView *subview in view.subviews) {
|
||||||
|
if (subview.layout.isIncluded) {
|
||||||
|
[subviewsToInclude addObject:subview];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL shouldReconstructChildList = NO;
|
||||||
|
if (YGNodeGetChildCount(node) != subviewsToInclude.count) {
|
||||||
|
shouldReconstructChildList = YES;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < subviewsToInclude.count; i++) {
|
||||||
|
if (YGNodeGetChild(node, i) != subviewsToInclude[i].layout.node) {
|
||||||
|
shouldReconstructChildList = YES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldReconstructChildList) {
|
||||||
|
YKRemoveAllChildren(node);
|
||||||
|
|
||||||
|
for (int i = 0 ; i < subviewsToInclude.count; i++) {
|
||||||
|
UIView *const subview = subviewsToInclude[i];
|
||||||
|
YGNodeInsertChild(node, subview.layout.node, i);
|
||||||
|
YKAttachNodesFromViewHierachy(subview.layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void YKRemoveAllChildren(const YGNodeRef node)
|
||||||
|
{
|
||||||
|
if (node == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (YGNodeGetChildCount(node) > 0) {
|
||||||
|
YGNodeRemoveChild(node, YGNodeGetChild(node, YGNodeGetChildCount(node) - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CGFloat YKRoundPixelValue(CGFloat value)
|
||||||
|
{
|
||||||
|
static CGFloat scale;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^(){
|
||||||
|
scale = [UIScreen mainScreen].scale;
|
||||||
|
});
|
||||||
|
|
||||||
|
return round(value * scale) / scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void YKApplyLayoutToViewHierarchy(YKLayout *layout) {
|
||||||
|
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread.");
|
||||||
|
|
||||||
|
if (!layout.isIncluded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
YGNodeRef node = layout.node;
|
||||||
|
const CGPoint topLeft = {
|
||||||
|
YGNodeLayoutGetLeft(node),
|
||||||
|
YGNodeLayoutGetTop(node),
|
||||||
|
};
|
||||||
|
|
||||||
|
const CGPoint bottomRight = {
|
||||||
|
topLeft.x + YGNodeLayoutGetWidth(node),
|
||||||
|
topLeft.y + YGNodeLayoutGetHeight(node),
|
||||||
|
};
|
||||||
|
|
||||||
|
UIView *view = layout.view;
|
||||||
|
view.frame = (CGRect) {
|
||||||
|
.origin = {
|
||||||
|
.x = YKRoundPixelValue(topLeft.x),
|
||||||
|
.y = YKRoundPixelValue(topLeft.y),
|
||||||
|
},
|
||||||
|
.size = {
|
||||||
|
.width = YKRoundPixelValue(bottomRight.x) - YKRoundPixelValue(topLeft.x),
|
||||||
|
.height = YKRoundPixelValue(bottomRight.y) - YKRoundPixelValue(topLeft.y),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const BOOL isLeaf = !layout.isEnabled || view.subviews.count == 0;
|
||||||
|
if (!isLeaf) {
|
||||||
|
for (NSUInteger i = 0; i < view.subviews.count; i++) {
|
||||||
|
YKApplyLayoutToViewHierarchy(view.subviews[i].layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
@@ -11,40 +11,45 @@
|
|||||||
13687D4B1DF8748400E7C260 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13687D4A1DF8748400E7C260 /* AppDelegate.m */; };
|
13687D4B1DF8748400E7C260 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13687D4A1DF8748400E7C260 /* AppDelegate.m */; };
|
||||||
13687D4E1DF8748400E7C260 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13687D4D1DF8748400E7C260 /* ViewController.m */; };
|
13687D4E1DF8748400E7C260 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13687D4D1DF8748400E7C260 /* ViewController.m */; };
|
||||||
13687D531DF8748400E7C260 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13687D521DF8748400E7C260 /* Assets.xcassets */; };
|
13687D531DF8748400E7C260 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13687D521DF8748400E7C260 /* Assets.xcassets */; };
|
||||||
13687D781DF878C600E7C260 /* YGEnums.h in yoga */ = {isa = PBXBuildFile; fileRef = 13687D5E1DF8778F00E7C260 /* YGEnums.h */; };
|
|
||||||
13687D791DF878C600E7C260 /* YGMacros.h in yoga */ = {isa = PBXBuildFile; fileRef = 13687D5F1DF8778F00E7C260 /* YGMacros.h */; };
|
|
||||||
13687D7A1DF878C600E7C260 /* Yoga.h in yoga */ = {isa = PBXBuildFile; fileRef = 13687D631DF8778F00E7C260 /* Yoga.h */; };
|
|
||||||
13687D7C1DF878DD00E7C260 /* UIView+Yoga.h in YogaKit */ = {isa = PBXBuildFile; fileRef = 13687D691DF8778F00E7C260 /* UIView+Yoga.h */; };
|
|
||||||
13687D801DF87CEC00E7C260 /* UIView+Yoga.m in Sources */ = {isa = PBXBuildFile; fileRef = 13687D6A1DF8778F00E7C260 /* UIView+Yoga.m */; };
|
|
||||||
13687D811DF87CF200E7C260 /* YGNodeList.c in Sources */ = {isa = PBXBuildFile; fileRef = 13687D601DF8778F00E7C260 /* YGNodeList.c */; };
|
|
||||||
13687D821DF87CF200E7C260 /* Yoga.c in Sources */ = {isa = PBXBuildFile; fileRef = 13687D621DF8778F00E7C260 /* Yoga.c */; };
|
|
||||||
13687D851DF87D1E00E7C260 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13687D841DF87D1E00E7C260 /* UIKit.framework */; };
|
13687D851DF87D1E00E7C260 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13687D841DF87D1E00E7C260 /* UIKit.framework */; };
|
||||||
13687D871DF87D2400E7C260 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13687D861DF87D2400E7C260 /* Foundation.framework */; };
|
13687D871DF87D2400E7C260 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13687D861DF87D2400E7C260 /* Foundation.framework */; };
|
||||||
|
63EE08411E06ED3D00EE5F9A /* YogaKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 63EE083F1E06ED3D00EE5F9A /* YogaKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
63EE08441E06ED3D00EE5F9A /* YogaKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63EE083D1E06ED3D00EE5F9A /* YogaKit.framework */; };
|
||||||
|
63EE08451E06ED3D00EE5F9A /* YogaKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 63EE083D1E06ED3D00EE5F9A /* YogaKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
63EE084A1E06EEB700EE5F9A /* YGNodeList.c in Sources */ = {isa = PBXBuildFile; fileRef = 13687D601DF8778F00E7C260 /* YGNodeList.c */; };
|
||||||
|
63EE084B1E06EEB700EE5F9A /* Yoga.c in Sources */ = {isa = PBXBuildFile; fileRef = 13687D621DF8778F00E7C260 /* Yoga.c */; };
|
||||||
|
63EE084C1E06EEB700EE5F9A /* UIView+YogaKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 13687D6A1DF8778F00E7C260 /* UIView+YogaKit.m */; };
|
||||||
|
63EE084E1E06EECB00EE5F9A /* YGMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 13687D5F1DF8778F00E7C260 /* YGMacros.h */; };
|
||||||
|
63EE084F1E06EECB00EE5F9A /* YGNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = 13687D611DF8778F00E7C260 /* YGNodeList.h */; };
|
||||||
|
63EE08501E06EECB00EE5F9A /* Yoga.h in Headers */ = {isa = PBXBuildFile; fileRef = 13687D631DF8778F00E7C260 /* Yoga.h */; };
|
||||||
|
63EE08511E06EECB00EE5F9A /* UIView+YogaKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 13687D691DF8778F00E7C260 /* UIView+YogaKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
63EE08531E06F3D100EE5F9A /* YKEnums.h in Headers */ = {isa = PBXBuildFile; fileRef = 63EE08521E06F3D100EE5F9A /* YKEnums.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
63EE08551E072EF800EE5F9A /* SwiftViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63EE08541E072EF800EE5F9A /* SwiftViewController.swift */; };
|
||||||
|
63EE08571E07590C00EE5F9A /* YKLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 63EE08561E07590C00EE5F9A /* YKLayout.m */; };
|
||||||
|
63EE08591E07598A00EE5F9A /* YKLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 63EE08581E07591A00EE5F9A /* YKLayout.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
63EE085B1E075B0B00EE5F9A /* YKLayout+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 63EE085A1E075AAA00EE5F9A /* YKLayout+Private.h */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
13687D771DF878A000E7C260 /* yoga */ = {
|
63EE08421E06ED3D00EE5F9A /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXContainerItemProxy;
|
||||||
buildActionMask = 2147483647;
|
containerPortal = 13687D3B1DF8748300E7C260 /* Project object */;
|
||||||
dstPath = include/yoga;
|
proxyType = 1;
|
||||||
dstSubfolderSpec = 16;
|
remoteGlobalIDString = 63EE083C1E06ED3D00EE5F9A;
|
||||||
files = (
|
remoteInfo = YogaKit;
|
||||||
13687D781DF878C600E7C260 /* YGEnums.h in yoga */,
|
|
||||||
13687D791DF878C600E7C260 /* YGMacros.h in yoga */,
|
|
||||||
13687D7A1DF878C600E7C260 /* Yoga.h in yoga */,
|
|
||||||
);
|
|
||||||
name = yoga;
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
};
|
||||||
13687D7B1DF878CE00E7C260 /* YogaKit */ = {
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
63EE08491E06ED3D00EE5F9A /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
dstPath = include/YogaKit;
|
dstPath = "";
|
||||||
dstSubfolderSpec = 16;
|
dstSubfolderSpec = 10;
|
||||||
files = (
|
files = (
|
||||||
13687D7C1DF878DD00E7C260 /* UIView+Yoga.h in YogaKit */,
|
63EE08451E06ED3D00EE5F9A /* YogaKit.framework in Embed Frameworks */,
|
||||||
);
|
);
|
||||||
name = YogaKit;
|
name = "Embed Frameworks";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
@@ -58,16 +63,23 @@
|
|||||||
13687D4D1DF8748400E7C260 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
13687D4D1DF8748400E7C260 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
||||||
13687D521DF8748400E7C260 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
13687D521DF8748400E7C260 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
13687D571DF8748400E7C260 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
13687D571DF8748400E7C260 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
13687D5E1DF8778F00E7C260 /* YGEnums.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGEnums.h; sourceTree = "<group>"; };
|
|
||||||
13687D5F1DF8778F00E7C260 /* YGMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGMacros.h; sourceTree = "<group>"; };
|
13687D5F1DF8778F00E7C260 /* YGMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGMacros.h; sourceTree = "<group>"; };
|
||||||
13687D601DF8778F00E7C260 /* YGNodeList.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = YGNodeList.c; sourceTree = "<group>"; };
|
13687D601DF8778F00E7C260 /* YGNodeList.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = YGNodeList.c; sourceTree = "<group>"; };
|
||||||
13687D611DF8778F00E7C260 /* YGNodeList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGNodeList.h; sourceTree = "<group>"; };
|
13687D611DF8778F00E7C260 /* YGNodeList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGNodeList.h; sourceTree = "<group>"; };
|
||||||
13687D621DF8778F00E7C260 /* Yoga.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Yoga.c; sourceTree = "<group>"; };
|
13687D621DF8778F00E7C260 /* Yoga.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Yoga.c; sourceTree = "<group>"; };
|
||||||
13687D631DF8778F00E7C260 /* Yoga.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Yoga.h; sourceTree = "<group>"; };
|
13687D631DF8778F00E7C260 /* Yoga.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Yoga.h; sourceTree = "<group>"; };
|
||||||
13687D691DF8778F00E7C260 /* UIView+Yoga.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+Yoga.h"; sourceTree = "<group>"; };
|
13687D691DF8778F00E7C260 /* UIView+YogaKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "UIView+YogaKit.h"; path = "../../UIView+YogaKit.h"; sourceTree = "<group>"; };
|
||||||
13687D6A1DF8778F00E7C260 /* UIView+Yoga.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+Yoga.m"; sourceTree = "<group>"; };
|
13687D6A1DF8778F00E7C260 /* UIView+YogaKit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "UIView+YogaKit.m"; path = "../../UIView+YogaKit.m"; sourceTree = "<group>"; };
|
||||||
13687D841DF87D1E00E7C260 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
13687D841DF87D1E00E7C260 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||||
13687D861DF87D2400E7C260 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
13687D861DF87D2400E7C260 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||||
|
63EE083D1E06ED3D00EE5F9A /* YogaKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = YogaKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
63EE083F1E06ED3D00EE5F9A /* YogaKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YogaKit.h; sourceTree = "<group>"; };
|
||||||
|
63EE08401E06ED3D00EE5F9A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
63EE08521E06F3D100EE5F9A /* YKEnums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YKEnums.h; path = ../../YKEnums.h; sourceTree = "<group>"; };
|
||||||
|
63EE08541E072EF800EE5F9A /* SwiftViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftViewController.swift; sourceTree = "<group>"; };
|
||||||
|
63EE08561E07590C00EE5F9A /* YKLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = YKLayout.m; path = ../../YKLayout.m; sourceTree = "<group>"; };
|
||||||
|
63EE08581E07591A00EE5F9A /* YKLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = YKLayout.h; path = ../../YKLayout.h; sourceTree = "<group>"; };
|
||||||
|
63EE085A1E075AAA00EE5F9A /* YKLayout+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "YKLayout+Private.h"; path = "../../YKLayout+Private.h"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -77,6 +89,14 @@
|
|||||||
files = (
|
files = (
|
||||||
13687D871DF87D2400E7C260 /* Foundation.framework in Frameworks */,
|
13687D871DF87D2400E7C260 /* Foundation.framework in Frameworks */,
|
||||||
13687D851DF87D1E00E7C260 /* UIKit.framework in Frameworks */,
|
13687D851DF87D1E00E7C260 /* UIKit.framework in Frameworks */,
|
||||||
|
63EE08441E06ED3D00EE5F9A /* YogaKit.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
63EE08391E06ED3D00EE5F9A /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -86,9 +106,8 @@
|
|||||||
13687D3A1DF8748300E7C260 = {
|
13687D3A1DF8748300E7C260 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13687D5D1DF8778F00E7C260 /* yoga */,
|
|
||||||
13687D641DF8778F00E7C260 /* YogaKit */,
|
|
||||||
13687D451DF8748400E7C260 /* YogaKitSample */,
|
13687D451DF8748400E7C260 /* YogaKitSample */,
|
||||||
|
63EE083E1E06ED3D00EE5F9A /* YogaKit */,
|
||||||
13687D441DF8748400E7C260 /* Products */,
|
13687D441DF8748400E7C260 /* Products */,
|
||||||
13687D831DF87D1E00E7C260 /* Frameworks */,
|
13687D831DF87D1E00E7C260 /* Frameworks */,
|
||||||
);
|
);
|
||||||
@@ -98,6 +117,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13687D431DF8748400E7C260 /* YogaKitSample.app */,
|
13687D431DF8748400E7C260 /* YogaKitSample.app */,
|
||||||
|
63EE083D1E06ED3D00EE5F9A /* YogaKit.framework */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -109,6 +129,7 @@
|
|||||||
13687D4A1DF8748400E7C260 /* AppDelegate.m */,
|
13687D4A1DF8748400E7C260 /* AppDelegate.m */,
|
||||||
13687D4C1DF8748400E7C260 /* ViewController.h */,
|
13687D4C1DF8748400E7C260 /* ViewController.h */,
|
||||||
13687D4D1DF8748400E7C260 /* ViewController.m */,
|
13687D4D1DF8748400E7C260 /* ViewController.m */,
|
||||||
|
63EE08541E072EF800EE5F9A /* SwiftViewController.swift */,
|
||||||
13687D521DF8748400E7C260 /* Assets.xcassets */,
|
13687D521DF8748400E7C260 /* Assets.xcassets */,
|
||||||
13687D571DF8748400E7C260 /* Info.plist */,
|
13687D571DF8748400E7C260 /* Info.plist */,
|
||||||
13687D461DF8748400E7C260 /* Supporting Files */,
|
13687D461DF8748400E7C260 /* Supporting Files */,
|
||||||
@@ -127,7 +148,6 @@
|
|||||||
13687D5D1DF8778F00E7C260 /* yoga */ = {
|
13687D5D1DF8778F00E7C260 /* yoga */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13687D5E1DF8778F00E7C260 /* YGEnums.h */,
|
|
||||||
13687D5F1DF8778F00E7C260 /* YGMacros.h */,
|
13687D5F1DF8778F00E7C260 /* YGMacros.h */,
|
||||||
13687D601DF8778F00E7C260 /* YGNodeList.c */,
|
13687D601DF8778F00E7C260 /* YGNodeList.c */,
|
||||||
13687D611DF8778F00E7C260 /* YGNodeList.h */,
|
13687D611DF8778F00E7C260 /* YGNodeList.h */,
|
||||||
@@ -135,17 +155,7 @@
|
|||||||
13687D631DF8778F00E7C260 /* Yoga.h */,
|
13687D631DF8778F00E7C260 /* Yoga.h */,
|
||||||
);
|
);
|
||||||
name = yoga;
|
name = yoga;
|
||||||
path = ../../yoga;
|
path = ../../../yoga;
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
13687D641DF8778F00E7C260 /* YogaKit */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
13687D691DF8778F00E7C260 /* UIView+Yoga.h */,
|
|
||||||
13687D6A1DF8778F00E7C260 /* UIView+Yoga.m */,
|
|
||||||
);
|
|
||||||
name = YogaKit;
|
|
||||||
path = ..;
|
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
13687D831DF87D1E00E7C260 /* Frameworks */ = {
|
13687D831DF87D1E00E7C260 /* Frameworks */ = {
|
||||||
@@ -157,44 +167,101 @@
|
|||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
63EE083E1E06ED3D00EE5F9A /* YogaKit */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
13687D5D1DF8778F00E7C260 /* yoga */,
|
||||||
|
63EE083F1E06ED3D00EE5F9A /* YogaKit.h */,
|
||||||
|
63EE08521E06F3D100EE5F9A /* YKEnums.h */,
|
||||||
|
13687D691DF8778F00E7C260 /* UIView+YogaKit.h */,
|
||||||
|
13687D6A1DF8778F00E7C260 /* UIView+YogaKit.m */,
|
||||||
|
63EE08581E07591A00EE5F9A /* YKLayout.h */,
|
||||||
|
63EE085A1E075AAA00EE5F9A /* YKLayout+Private.h */,
|
||||||
|
63EE08561E07590C00EE5F9A /* YKLayout.m */,
|
||||||
|
63EE08401E06ED3D00EE5F9A /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = YogaKit;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXHeadersBuildPhase section */
|
||||||
|
63EE083A1E06ED3D00EE5F9A /* Headers */ = {
|
||||||
|
isa = PBXHeadersBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
63EE085B1E075B0B00EE5F9A /* YKLayout+Private.h in Headers */,
|
||||||
|
63EE08591E07598A00EE5F9A /* YKLayout.h in Headers */,
|
||||||
|
63EE08411E06ED3D00EE5F9A /* YogaKit.h in Headers */,
|
||||||
|
63EE08531E06F3D100EE5F9A /* YKEnums.h in Headers */,
|
||||||
|
63EE08511E06EECB00EE5F9A /* UIView+YogaKit.h in Headers */,
|
||||||
|
63EE084E1E06EECB00EE5F9A /* YGMacros.h in Headers */,
|
||||||
|
63EE084F1E06EECB00EE5F9A /* YGNodeList.h in Headers */,
|
||||||
|
63EE08501E06EECB00EE5F9A /* Yoga.h in Headers */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXHeadersBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
13687D421DF8748300E7C260 /* YogaKitSample */ = {
|
13687D421DF8748300E7C260 /* YogaKitSample */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 13687D5A1DF8748400E7C260 /* Build configuration list for PBXNativeTarget "YogaKitSample" */;
|
buildConfigurationList = 13687D5A1DF8748400E7C260 /* Build configuration list for PBXNativeTarget "YogaKitSample" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
13687D771DF878A000E7C260 /* yoga */,
|
|
||||||
13687D7B1DF878CE00E7C260 /* YogaKit */,
|
|
||||||
13687D3F1DF8748300E7C260 /* Sources */,
|
13687D3F1DF8748300E7C260 /* Sources */,
|
||||||
13687D401DF8748300E7C260 /* Frameworks */,
|
13687D401DF8748300E7C260 /* Frameworks */,
|
||||||
13687D411DF8748300E7C260 /* Resources */,
|
13687D411DF8748300E7C260 /* Resources */,
|
||||||
|
63EE08491E06ED3D00EE5F9A /* Embed Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
63EE08431E06ED3D00EE5F9A /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = YogaKitSample;
|
name = YogaKitSample;
|
||||||
productName = YogaKitSample;
|
productName = YogaKitSample;
|
||||||
productReference = 13687D431DF8748400E7C260 /* YogaKitSample.app */;
|
productReference = 13687D431DF8748400E7C260 /* YogaKitSample.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
|
63EE083C1E06ED3D00EE5F9A /* YogaKit */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 63EE08481E06ED3D00EE5F9A /* Build configuration list for PBXNativeTarget "YogaKit" */;
|
||||||
|
buildPhases = (
|
||||||
|
63EE08381E06ED3D00EE5F9A /* Sources */,
|
||||||
|
63EE08391E06ED3D00EE5F9A /* Frameworks */,
|
||||||
|
63EE083A1E06ED3D00EE5F9A /* Headers */,
|
||||||
|
63EE083B1E06ED3D00EE5F9A /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = YogaKit;
|
||||||
|
productName = YogaKit;
|
||||||
|
productReference = 63EE083D1E06ED3D00EE5F9A /* YogaKit.framework */;
|
||||||
|
productType = "com.apple.product-type.framework";
|
||||||
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
13687D3B1DF8748300E7C260 /* Project object */ = {
|
13687D3B1DF8748300E7C260 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0810;
|
LastUpgradeCheck = 0820;
|
||||||
ORGANIZATIONNAME = facebook;
|
ORGANIZATIONNAME = facebook;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
13687D421DF8748300E7C260 = {
|
13687D421DF8748300E7C260 = {
|
||||||
CreatedOnToolsVersion = 8.1;
|
CreatedOnToolsVersion = 8.1;
|
||||||
|
LastSwiftMigration = 0820;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
|
};
|
||||||
|
63EE083C1E06ED3D00EE5F9A = {
|
||||||
|
CreatedOnToolsVersion = 8.2;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 13687D3E1DF8748300E7C260 /* Build configuration list for PBXProject "YogaKitSample" */;
|
buildConfigurationList = 13687D3E1DF8748300E7C260 /* Build configuration list for PBXProject "YogaKit" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 3.2";
|
||||||
developmentRegion = English;
|
developmentRegion = English;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
@@ -207,6 +274,7 @@
|
|||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
|
63EE083C1E06ED3D00EE5F9A /* YogaKit */,
|
||||||
13687D421DF8748300E7C260 /* YogaKitSample */,
|
13687D421DF8748300E7C260 /* YogaKitSample */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -221,6 +289,13 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
63EE083B1E06ED3D00EE5F9A /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@@ -228,17 +303,34 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
13687D801DF87CEC00E7C260 /* UIView+Yoga.m in Sources */,
|
63EE08551E072EF800EE5F9A /* SwiftViewController.swift in Sources */,
|
||||||
13687D4E1DF8748400E7C260 /* ViewController.m in Sources */,
|
13687D4E1DF8748400E7C260 /* ViewController.m in Sources */,
|
||||||
13687D4B1DF8748400E7C260 /* AppDelegate.m in Sources */,
|
13687D4B1DF8748400E7C260 /* AppDelegate.m in Sources */,
|
||||||
13687D821DF87CF200E7C260 /* Yoga.c in Sources */,
|
|
||||||
13687D811DF87CF200E7C260 /* YGNodeList.c in Sources */,
|
|
||||||
13687D481DF8748400E7C260 /* main.m in Sources */,
|
13687D481DF8748400E7C260 /* main.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
63EE08381E06ED3D00EE5F9A /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
63EE084A1E06EEB700EE5F9A /* YGNodeList.c in Sources */,
|
||||||
|
63EE084B1E06EEB700EE5F9A /* Yoga.c in Sources */,
|
||||||
|
63EE084C1E06EEB700EE5F9A /* UIView+YogaKit.m in Sources */,
|
||||||
|
63EE08571E07590C00EE5F9A /* YKLayout.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
63EE08431E06ED3D00EE5F9A /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 63EE083C1E06ED3D00EE5F9A /* YogaKit */;
|
||||||
|
targetProxy = 63EE08421E06ED3D00EE5F9A /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
13687D581DF8748400E7C260 /* Debug */ = {
|
13687D581DF8748400E7C260 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
@@ -258,6 +350,7 @@
|
|||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
@@ -305,6 +398,7 @@
|
|||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
@@ -332,10 +426,13 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
INFOPLIST_FILE = YogaKitSample/Info.plist;
|
INFOPLIST_FILE = YogaKitSample/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -343,17 +440,65 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
INFOPLIST_FILE = YogaKitSample/Info.plist;
|
INFOPLIST_FILE = YogaKitSample/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
63EE08461E06ED3D00EE5F9A /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "";
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEFINES_MODULE = YES;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
|
INFOPLIST_FILE = YogaKit/Info.plist;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKit;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
VERSION_INFO_PREFIX = "";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
63EE08471E06ED3D00EE5F9A /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "";
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEFINES_MODULE = YES;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
|
INFOPLIST_FILE = YogaKit/Info.plist;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKit;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
VERSION_INFO_PREFIX = "";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
13687D3E1DF8748300E7C260 /* Build configuration list for PBXProject "YogaKitSample" */ = {
|
13687D3E1DF8748300E7C260 /* Build configuration list for PBXProject "YogaKit" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
13687D581DF8748400E7C260 /* Debug */,
|
13687D581DF8748400E7C260 /* Debug */,
|
||||||
@@ -369,6 +514,16 @@
|
|||||||
13687D5C1DF8748400E7C260 /* Release */,
|
13687D5C1DF8748400E7C260 /* Release */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
63EE08481E06ED3D00EE5F9A /* Build configuration list for PBXNativeTarget "YogaKit" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
63EE08461E06ED3D00EE5F9A /* Debug */,
|
||||||
|
63EE08471E06ED3D00EE5F9A /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
};
|
};
|
@@ -2,6 +2,6 @@
|
|||||||
<Workspace
|
<Workspace
|
||||||
version = "1.0">
|
version = "1.0">
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "self:YogaKitSample.xcodeproj">
|
location = "self:/Users/david/Projects/yoga/YogaKit/YogaKit/YogaKit.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0810"
|
LastUpgradeVersion = "0820"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -14,10 +14,10 @@
|
|||||||
buildForAnalyzing = "YES">
|
buildForAnalyzing = "YES">
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "13687D421DF8748300E7C260"
|
BlueprintIdentifier = "63EE083C1E06ED3D00EE5F9A"
|
||||||
BuildableName = "YogaKitSample.app"
|
BuildableName = "YogaKit.framework"
|
||||||
BlueprintName = "YogaKitSample"
|
BlueprintName = "YogaKit"
|
||||||
ReferencedContainer = "container:YogaKitSample.xcodeproj">
|
ReferencedContainer = "container:YogaKit.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildActionEntry>
|
</BuildActionEntry>
|
||||||
</BuildActionEntries>
|
</BuildActionEntries>
|
||||||
@@ -29,15 +29,6 @@
|
|||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
</Testables>
|
</Testables>
|
||||||
<MacroExpansion>
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "13687D421DF8748300E7C260"
|
|
||||||
BuildableName = "YogaKitSample.app"
|
|
||||||
BlueprintName = "YogaKitSample"
|
|
||||||
ReferencedContainer = "container:YogaKitSample.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</MacroExpansion>
|
|
||||||
<AdditionalOptions>
|
<AdditionalOptions>
|
||||||
</AdditionalOptions>
|
</AdditionalOptions>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
@@ -51,16 +42,15 @@
|
|||||||
debugDocumentVersioning = "YES"
|
debugDocumentVersioning = "YES"
|
||||||
debugServiceExtension = "internal"
|
debugServiceExtension = "internal"
|
||||||
allowLocationSimulation = "YES">
|
allowLocationSimulation = "YES">
|
||||||
<BuildableProductRunnable
|
<MacroExpansion>
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "13687D421DF8748300E7C260"
|
BlueprintIdentifier = "63EE083C1E06ED3D00EE5F9A"
|
||||||
BuildableName = "YogaKitSample.app"
|
BuildableName = "YogaKit.framework"
|
||||||
BlueprintName = "YogaKitSample"
|
BlueprintName = "YogaKit"
|
||||||
ReferencedContainer = "container:YogaKitSample.xcodeproj">
|
ReferencedContainer = "container:YogaKit.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</MacroExpansion>
|
||||||
<AdditionalOptions>
|
<AdditionalOptions>
|
||||||
</AdditionalOptions>
|
</AdditionalOptions>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
@@ -70,16 +60,15 @@
|
|||||||
savedToolIdentifier = ""
|
savedToolIdentifier = ""
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
debugDocumentVersioning = "YES">
|
debugDocumentVersioning = "YES">
|
||||||
<BuildableProductRunnable
|
<MacroExpansion>
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "13687D421DF8748300E7C260"
|
BlueprintIdentifier = "63EE083C1E06ED3D00EE5F9A"
|
||||||
BuildableName = "YogaKitSample.app"
|
BuildableName = "YogaKit.framework"
|
||||||
BlueprintName = "YogaKitSample"
|
BlueprintName = "YogaKit"
|
||||||
ReferencedContainer = "container:YogaKitSample.xcodeproj">
|
ReferencedContainer = "container:YogaKit.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</MacroExpansion>
|
||||||
</ProfileAction>
|
</ProfileAction>
|
||||||
<AnalyzeAction
|
<AnalyzeAction
|
||||||
buildConfiguration = "Debug">
|
buildConfiguration = "Debug">
|
24
YogaKit/YogaKit/YogaKit/Info.plist
Normal file
24
YogaKit/YogaKit/YogaKit/Info.plist
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
18
YogaKit/YogaKit/YogaKit/YogaKit.h
Normal file
18
YogaKit/YogaKit/YogaKit/YogaKit.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// YogaKit.h
|
||||||
|
// YogaKit
|
||||||
|
//
|
||||||
|
// Created by David Hart on 18.12.16.
|
||||||
|
// Copyright © 2016 facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
//! Project version number for YogaKit.
|
||||||
|
FOUNDATION_EXPORT double YogaKitVersionNumber;
|
||||||
|
|
||||||
|
//! Project version string for YogaKit.
|
||||||
|
FOUNDATION_EXPORT const unsigned char YogaKitVersionString[];
|
||||||
|
|
||||||
|
#import <YogaKit/UIView+YogaKit.h>
|
||||||
|
#import <YogaKit/YKEnums.h>
|
41
YogaKit/YogaKit/YogaKitSample/SwiftViewController.swift
Normal file
41
YogaKit/YogaKit/YogaKitSample/SwiftViewController.swift
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// SwiftViewController.swift
|
||||||
|
// YogaKit
|
||||||
|
//
|
||||||
|
// Created by David Hart on 18.12.16.
|
||||||
|
// Copyright © 2016 facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import YogaKit
|
||||||
|
|
||||||
|
class SwiftViewController : UIViewController {
|
||||||
|
override func viewDidLoad() {
|
||||||
|
let root = view!
|
||||||
|
root.backgroundColor = .red
|
||||||
|
root.layout.isEnabled = true
|
||||||
|
root.layout.width = view.bounds.size.width
|
||||||
|
root.layout.height = view.bounds.size.height
|
||||||
|
root.layout.alignItems = .center
|
||||||
|
root.layout.justifyContent = .center
|
||||||
|
|
||||||
|
let child1 = UIView()
|
||||||
|
child1.backgroundColor = .blue
|
||||||
|
child1.layout.isEnabled = true
|
||||||
|
child1.layout.width = 100
|
||||||
|
child1.layout.height = 100
|
||||||
|
|
||||||
|
let child2 = UIView()
|
||||||
|
child2.backgroundColor = .green
|
||||||
|
child2.frame = CGRect(origin: .zero, size: CGSize(width: 200, height: 100))
|
||||||
|
|
||||||
|
let child3 = UIView()
|
||||||
|
child3.backgroundColor = .yellow
|
||||||
|
child3.frame = CGRect(origin: .zero, size: CGSize(width: 100, height: 100))
|
||||||
|
|
||||||
|
child2.addSubview(child3)
|
||||||
|
root.addSubview(child1)
|
||||||
|
root.addSubview(child2)
|
||||||
|
root.layout.apply()
|
||||||
|
}
|
||||||
|
}
|
@@ -10,6 +10,5 @@
|
|||||||
|
|
||||||
@interface ViewController : UIViewController
|
@interface ViewController : UIViewController
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
@@ -7,8 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#import "ViewController.h"
|
#import "ViewController.h"
|
||||||
|
#import <YogaKit/YogaKit.h>
|
||||||
#import <YogaKit/UIView+Yoga.h>
|
|
||||||
|
|
||||||
@interface ViewController ()
|
@interface ViewController ()
|
||||||
|
|
||||||
@@ -20,17 +19,17 @@
|
|||||||
{
|
{
|
||||||
UIView *root = self.view;
|
UIView *root = self.view;
|
||||||
root.backgroundColor = [UIColor redColor];
|
root.backgroundColor = [UIColor redColor];
|
||||||
[root yg_setUsesYoga:YES];
|
root.layout.isEnabled = YES;
|
||||||
[root yg_setWidth:self.view.bounds.size.width];
|
root.layout.width = self.view.bounds.size.width;
|
||||||
[root yg_setHeight:self.view.bounds.size.height];
|
root.layout.height = self.view.bounds.size.height;
|
||||||
[root yg_setAlignItems:YGAlignCenter];
|
root.layout.alignItems = YKAlignCenter;
|
||||||
[root yg_setJustifyContent:YGJustifyCenter];
|
root.layout.justifyContent = YKJustifyCenter;
|
||||||
|
|
||||||
UIView *child1 = [UIView new];
|
UIView *child1 = [UIView new];
|
||||||
child1.backgroundColor = [UIColor blueColor];
|
child1.backgroundColor = [UIColor blueColor];
|
||||||
[child1 yg_setUsesYoga:YES];
|
child1.layout.isEnabled = YES;
|
||||||
[child1 yg_setWidth:100];
|
child1.layout.width = 100;
|
||||||
[child1 yg_setHeight:100];
|
child1.layout.height = 100;
|
||||||
|
|
||||||
UIView *child2 = [UIView new];
|
UIView *child2 = [UIView new];
|
||||||
child2.backgroundColor = [UIColor greenColor];
|
child2.backgroundColor = [UIColor greenColor];
|
||||||
@@ -53,7 +52,7 @@
|
|||||||
[child2 addSubview:child3];
|
[child2 addSubview:child3];
|
||||||
[root addSubview:child1];
|
[root addSubview:child1];
|
||||||
[root addSubview:child2];
|
[root addSubview:child2];
|
||||||
[root yg_applyLayout];
|
[root.layout apply];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>SchemeUserState</key>
|
|
||||||
<dict>
|
|
||||||
<key>YogaKitSample.xcscheme</key>
|
|
||||||
<dict>
|
|
||||||
<key>orderHint</key>
|
|
||||||
<integer>0</integer>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>SuppressBuildableAutocreation</key>
|
|
||||||
<dict>
|
|
||||||
<key>13687D421DF8748300E7C260</key>
|
|
||||||
<dict>
|
|
||||||
<key>primary</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
31
enums.py
31
enums.py
@@ -89,6 +89,21 @@ ENUMS = {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OBJC_ENUMS = {
|
||||||
|
'Direction': [
|
||||||
|
'Inherit',
|
||||||
|
'LeftToRight',
|
||||||
|
'RightToLeft',
|
||||||
|
],
|
||||||
|
'Edge': None,
|
||||||
|
'MeasureMode': None,
|
||||||
|
'PrintOptions': None,
|
||||||
|
'Dimension': None,
|
||||||
|
'LogLevel': None,
|
||||||
|
'Overflow': None,
|
||||||
|
'ExperimentalFeature': None
|
||||||
|
}
|
||||||
|
|
||||||
LICENSE = """/**
|
LICENSE = """/**
|
||||||
* Copyright (c) 2014-present, Facebook, Inc.
|
* Copyright (c) 2014-present, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@@ -187,3 +202,19 @@ for name, values in ENUMS.items():
|
|||||||
f.write(' %s,\n' % value)
|
f.write(' %s,\n' % value)
|
||||||
f.write(' }\n')
|
f.write(' }\n')
|
||||||
f.write('}\n')
|
f.write('}\n')
|
||||||
|
|
||||||
|
# write out objc files
|
||||||
|
with open(root + '/YogaKit/YKEnums.h', 'w') as f:
|
||||||
|
objc_enums = ENUMS
|
||||||
|
objc_enums.update(OBJC_ENUMS)
|
||||||
|
f.write(LICENSE)
|
||||||
|
for name, values in objc_enums.items():
|
||||||
|
if values is not None:
|
||||||
|
f.write('typedef NS_ENUM(NSInteger, YK%s) {\n' % name)
|
||||||
|
for value in values:
|
||||||
|
if isinstance(value, tuple):
|
||||||
|
f.write(' YK%s%s = %d,\n' % (name, value[0], value[1]))
|
||||||
|
else:
|
||||||
|
f.write(' YK%s%s,\n' % (name, value))
|
||||||
|
f.write('} NS_SWIFT_NAME(%s);\n' % name)
|
||||||
|
f.write('\n')
|
||||||
|
Reference in New Issue
Block a user
Personally, I find this makes the API much more confusing. There are multiple properties that essentially do the same thing. I could set
positionLeft
andpositionRight
or just simply setpositionHorizontal
. To me, it would be much more idiomatic to Objective-C and Swift if we did something like this.or
where YKEdges is an NSOption.
I would apply this comment to
margin
andpadding
too. cc: @emilsjolander@dshahidehpour I agree the solution I have is not ideal, but I fail to see how
UIEdgeInsets
or aNS_OPTIONS YKEdges
would allow us to express theStart
andEnd
values.@hartbit Whoops, I didn't even notice those, do we think they need to part of
YogaKit
? I purposely left some properties out at first because I didn't see a huge use-case for them with UIKit.@dshahidehpour The Yoga website says: "We believe that Right-to-Left (RTL) should be a first class citizen when it comes to layout" and I strongly agree. UIKit also supports it by default with leading and trailing constraints in Auto Layout and I'd be very sorry to have them out of YogaKit.
You mention that there are multiple properties that do the same thing. But it's not unheard of in Cocoa. For example, a UIView's
frame.size
is the same as itsbounds.size
. Setting one affects the other. And it's the same with it'scenter
, which is the mid-x and mid-y offrame
.I know, this is a difficult design decision. But I think there is no perfect solution. For sake of discussion, here are the solutions I see, as well as their pros and cons.
Properties
Usage in Objective-C
Usage in Swift
Pros
Cons
Methods with
NS_ENUM
Usage in Objective-C
Usage in Swift
Pros
Cons
YGEdgeValue
Usage in Objective-C
Usage in Swift
Pros and Cons
This is basically a different flavor of properties. I'm not a hug fan of it because it multiplies the number of objects on the heap that yoga generates by 4 for a small gain in readability and API surface and a small loss in usage typing speed because having to go through two auto-completion hints (
padding
, thentop
).Conclusion
On and all, here's my ranking of preference:
As an additional support for the properties, I don't think it would surprise UIKit users because it is fairly idiomatic of the AutoLayout APIs:
Add to that the fact that CSS and React Native users would feel right a home.
Hey @hartbit, sorry I took so long to respond. I really appreciate the time you put into that response, and I support all of it 100%.
@emilsjolander I know we talked about
YGEdgeValue
, but, I think @hartbit makes a compelling case for why we should put these properties on the layout object.I like the YGEdgeValue the best, but why does it need to be a full class? In C/C++, the pattern would be lightweight structs for this kind of data set. That way I can do something like:
view.layout.padding = {.top = 10, .bottom = 10}
Or a hypothetical
view.layout.padding = YGCreateEdgeValues(...);