Summary:
We currently have a bug in `UIView+CSSLayout.m` that you can repro in a scenario like this:
```
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
[container css_setUsesFlexbox:YES];
[container css_setFlexDirection:CSSFlexDirectionRow];
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
[subview1 css_setUsesFlexbox:YES];
[subview1 css_setIncludeInLayout:NO];
[container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
[subview2 css_setUsesFlexbox:YES];
[subview2 css_setIncludeInLayout:NO];
[container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
[subview3 css_setUsesFlexbox:YES];
[subview3 css_setIncludeInLayout:YES];
[container addSubview:subview3];
[container css_applyLayout];
```
`subview3` (which is the only view whose is going to be included in layout calculation) is inserted at child index 2, instead of 0. This eventually can cause crash in CSSLayout.c because it will attempt access a child in the list which is null.
Reviewed By: emilsjolander
Differential Revision: D4215659
fbshipit-source-id: a615f50e51f85b15d3bdb437e55958865898b183
Summary: Implement aspect ratio as part of Yoga. Aspect ratio allows users of the library to specify the size of the undefined dimension in terms of an aspect ratio. See test cases for examples.
Reviewed By: gkassabli
Differential Revision: D4211458
fbshipit-source-id: f8d0d318369c7b529ee29e61a52b17d0cf3b396d
Summary:
When dealing with manual sizing in UIView's (or UIKit in general) we see a common pattern like so:
Below we have an example implementation of a view with two Labels that want to be stacked horizontally. If we don't pass a second string, we hide the second label and give up the available space to the first label. See below:
```
interface TitleSubtitleView : UIView
- (void)configureWithTitle:(NSString *)title subtitle:(NSString *)subtitle;
end
implementation {
UILabel *_titleLabel;
UILabel *_subtitleLabel;
}
....
- (void)configureWithTitle:(NSString *)title subtitle:(NSString *)subtitle {
_titleLabel.text = title;
if (subtitle.length > 0) {
_subtitleLabel.hidden = NO;
_subtitleLabel.text = subtitle;
} else {
_subtitleLabel.hidden = YES;
}
}
- (CGSize)sizeThatFits:(CGSize)size {
const CGSize titleSize = [_titleLabel sizeThatFits:size];
CGSize subtitleSize = CGSizeZero;
if (!_subtitleLabel.isHidden) {
subtitleSize = [_subtitleSize sizeThatFits:CGSizeMake(size.width - titleSize.width, size.height - titleSize.height)];
}
}
- (void)layoutSubviews {
[super layoutSubviews];
const CGSize titleSize = [_titleLabel sizeThatFits:size];
_titleLabel.frame = CGRectMake(0, 0, titleSize.width, titleSize.height);
if (!_subtitleLabel.isHidden) {
subtitleSize = [_subtitleSize sizeThatFits:CGSizeMake(size.width - titleSize.width, size.height - titleSize.height)];
_subtitleLabel.frame = CGRectMake(CGRectGetMaxX(_titleLabel.frame), 0, subtitleSize.width, subtitleSize.height);
}
}
```
The problem is with the CSSLayout framework, as long as your view is in hierarchy, it's going to be allocated space during layout calculation. The only way to fix the view above would be to completely remove it from view hierarchy if it isn't being used. The problem is that adding/removing views from hierarchy is much less performant than hiding.
As a result, we need a way to tell the CSSLayoutKit library that even though a view is in hierarchy, we don't want to include it in layout. With this diff, we could change the class to look like this:
```
interface TitleSubtitleView : UIView
- (void)configureWithTitle:(NSString *)title subtitle:(NSString *)subtitle;
end
implementation {
UILabel *_titleLabel;
UILabel *_subtitleLabel;
}
....
- (void)configureWithTitle:(NSString *)title subtitle:(NSString *)subtitle {
_titleLabel.text = title;
_subtitleLabel.text = subtitle;
const BOOL subtitleHasText = subtitle.length > 0;
_subtitleLabel.hidden = !subtitleHasText;
[_subtitleLabel css_includeInLayout:!subtitleHasText];
}
- (CGSize)sizeThatFits:(CGSize)size {
const intrinsicSize = [self css_intrinsicSize];
return CGSizeMake(MIN(size.width, intrinsicSize.width), MIN(size.height, intrinsicSize.height)));
}
- (void)layoutSubviews {
[super layoutSubviews];
[self css_applyLayout];
}
```
Reviewed By: emilsjolander
Differential Revision: D4189897
fbshipit-source-id: 403d11d84d47691e3ce0b5ac18a180b0e4c104c4
Summary: When I try to use this in practice, I have come to realize that css_sizeThatFits will 99% return to you the constrainedSize that you pass it, thus making it useless. Instead, we replace it with a new API that will tell you the optimal size of the resolved layout. From this we can choose to use that size, or scale it down.
Reviewed By: emilsjolander
Differential Revision: D4191873
fbshipit-source-id: d36a2850448d9d82f97e5ef4c7397778c2a14094
Summary: Java and csharp already use CSSWrap and not CSSWrapType. Let's consolidate and stick with the shorter of the two.
Reviewed By: gkassabli
Differential Revision: D4174257
fbshipit-source-id: ba0bfab996ba158b07863d8c72cf2a41262c9592
Summary: There is a little bit of tidying that was needed for this class. The documentation was inconsistent in the header, the static functions were prefixed with underscores (discouraged by apple). Cleaned it all up.
Reviewed By: rnystrom
Differential Revision: D4167936
fbshipit-source-id: 6e9a6e7fb78e3cff290b867a1ac0d5dd5cc9de5b
Summary:
When trying to integrate this into an Xcode project that already included CSSLayout.[c|h], we were getting a linker error.
Upon digging in, I found out that Xcode was becoming confused because the imports of the uikit library and the c library are both `#import <CSSLayout/CSSLayout.h>`. So, it needed a new name.
Reviewed By: emilsjolander
Differential Revision: D4162621
fbshipit-source-id: b5f7624eb29f1b9eaebbed5104ec9ea8a12ad2e5