Repository: carlSQ/FlexBoxLayout Branch: develop Commit: b7cb9468dde0 Files: 101 Total size: 396.6 KB Directory structure: gitextract_pjda7wnv/ ├── .github/ │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ └── ISSUE_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── Example/ │ ├── Example/ │ │ ├── FBAppDelegate.h │ │ ├── FBAppDelegate.m │ │ ├── FBFPSGraph.h │ │ ├── FBFPSGraph.m │ │ ├── FBFeedModel.h │ │ ├── FBFeedModel.m │ │ ├── FBFeedView.h │ │ ├── FBFeedView.m │ │ ├── FBTableViewController.h │ │ ├── FBTableViewController.m │ │ ├── FBViewController.h │ │ ├── FBViewController.m │ │ ├── FlexBoxLayout-Info.plist │ │ ├── FlexBoxLayout-Prefix.pch │ │ ├── Images.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.launchimage/ │ │ │ │ └── Contents.json │ │ │ ├── breaddoge.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── doge.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── forkingdog.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── phil.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── sark.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── sinojerk.imageset/ │ │ │ │ └── Contents.json │ │ │ └── sunnyxx.imageset/ │ │ │ └── Contents.json │ │ ├── Launch Screen.storyboard │ │ ├── Main.storyboard │ │ ├── data.json │ │ ├── en.lproj/ │ │ │ └── InfoPlist.strings │ │ └── main.m │ ├── FlexBoxLayout.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── FlexBoxLayout_Example.xcscheme │ ├── FlexBoxLayout.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── Podfile │ ├── Pods/ │ │ ├── Local Podspecs/ │ │ │ ├── CSSLayout.podspec.json │ │ │ └── FlexBoxLayout.podspec.json │ │ ├── Pods.xcodeproj/ │ │ │ └── project.pbxproj │ │ └── Target Support Files/ │ │ ├── FlexBoxLayout/ │ │ │ ├── FlexBoxLayout-dummy.m │ │ │ ├── FlexBoxLayout-prefix.pch │ │ │ ├── FlexBoxLayout-umbrella.h │ │ │ ├── FlexBoxLayout.modulemap │ │ │ ├── FlexBoxLayout.xcconfig │ │ │ └── Info.plist │ │ ├── Pods-FlexBoxLayout_Example/ │ │ │ ├── Info.plist │ │ │ ├── Pods-FlexBoxLayout_Example-acknowledgements.markdown │ │ │ ├── Pods-FlexBoxLayout_Example-acknowledgements.plist │ │ │ ├── Pods-FlexBoxLayout_Example-dummy.m │ │ │ ├── Pods-FlexBoxLayout_Example-frameworks.sh │ │ │ ├── Pods-FlexBoxLayout_Example-resources.sh │ │ │ ├── Pods-FlexBoxLayout_Example-umbrella.h │ │ │ ├── Pods-FlexBoxLayout_Example.debug.xcconfig │ │ │ ├── Pods-FlexBoxLayout_Example.modulemap │ │ │ └── Pods-FlexBoxLayout_Example.release.xcconfig │ │ └── Pods-FlexBoxLayout_Tests/ │ │ ├── Info.plist │ │ ├── Pods-FlexBoxLayout_Tests-acknowledgements.markdown │ │ ├── Pods-FlexBoxLayout_Tests-acknowledgements.plist │ │ ├── Pods-FlexBoxLayout_Tests-dummy.m │ │ ├── Pods-FlexBoxLayout_Tests-frameworks.sh │ │ ├── Pods-FlexBoxLayout_Tests-resources.sh │ │ ├── Pods-FlexBoxLayout_Tests-umbrella.h │ │ ├── Pods-FlexBoxLayout_Tests.debug.xcconfig │ │ ├── Pods-FlexBoxLayout_Tests.modulemap │ │ └── Pods-FlexBoxLayout_Tests.release.xcconfig │ └── Tests/ │ ├── Tests-Info.plist │ ├── Tests-Prefix.pch │ ├── Tests.m │ └── en.lproj/ │ └── InfoPlist.strings ├── FlexBoxLayout/ │ ├── Assets/ │ │ └── .gitkeep │ └── Classes/ │ ├── Component/ │ │ ├── FBLayoutDiv.h │ │ ├── FBLayoutDiv.m │ │ ├── UIScrollView+FBLayout.h │ │ ├── UIScrollView+FBLayout.m │ │ ├── UITableView+FBLayout.h │ │ ├── UITableView+FBLayout.m │ │ ├── UIView+CellStyle.h │ │ ├── UIView+CellStyle.m │ │ ├── UIView+FBLayout.h │ │ └── UIView+FBLayout.m │ ├── FlexBoxLayout.h │ ├── Layout/ │ │ ├── FBLayout+Private.h │ │ ├── FBLayout.h │ │ ├── FBLayout.m │ │ ├── FBLayoutProtocol.h │ │ ├── FBViewLayoutCache.h │ │ ├── FBViewLayoutCache.m │ │ ├── YGEnums.h │ │ ├── YGMacros.h │ │ ├── YGNodeList.c │ │ ├── YGNodeList.h │ │ ├── Yoga.c │ │ └── Yoga.h │ └── Transaction/ │ ├── FBAsyLayoutTransaction.h │ └── FBAsyLayoutTransaction.m ├── FlexBoxLayout.podspec ├── LICENSE └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at 835150773@qq.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ ================================================ FILE: .github/CONTRIBUTING.md ================================================ # Contributing Guidelines This document contains information and guidelines about contributing to this project. Please read it before you start participating. **Topics** * [Asking Questions](#asking-questions) * [Reporting Issues](#reporting-issues) * [Developers Certificate of Origin](#developers-certificate-of-origin) ## Asking Questions We don't use GitHub as a support forum. For any usage questions that are not specific to the project itself, please ask on [Stack Overflow](https://stackoverflow.com) instead. By doing so, you'll be more likely to quickly solve your problem, and you'll allow anyone else with the same question to find the answer. This also allows maintainers to focus on improving the project for others. ## Reporting Issues A great way to contribute to the project is to send a detailed issue when you encounter an problem. We always appreciate a well-written, thorough bug report. Check that the project issues database doesn't already include that problem or suggestion before submitting an issue. If you find a match, add a quick "+1" or "I have this problem too." Doing this helps prioritize the most common problems and requests. When reporting issues, please include the following: * The version of Xcode you're using * The version of iOS or macOS you're targeting * The full output of any stack trace or compiler error * A code snippet that reproduces the described behavior, if applicable * Any other details that would be useful in understanding the problem This information will help us review and fix your issue faster. ## Developer's Certificate of Origin By making a contribution to this project, I certify that: - (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or - (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or - (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. - (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. --- *Some of the ideas and wording for the statements above were based on work by the [Alamofire](https://github.com/Alamofire/Alamofire/blob/master/CONTRIBUTING.md) communities. We commend them for their efforts to facilitate collaboration in their projects.* ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ ### Check List Thanks for considering to open an issue. Before you submit your issue, please confirm these boxes are checked. - [ ] I have read the [README.md](https://github.com/LPD-iOS/FlexBoxLayout/blob/master/README.md), but there is no information I need. - [ ] I have searched in [existing issues](https://github.com/LPD-iOS/FlexBoxLayout/issues?utf8=%E2%9C%93&q=is%3Aissue), but did find a same one. ### Issue Description #### Description [Tell us about the issue] #### Reproduce [The steps to reproduce this issue. What are the parameters, where did you put your code, etc.] #### Other Comment [Add anything else here] ================================================ FILE: .gitignore ================================================ # OS X .DS_Store # Xcode build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata/ *.xccheckout profile *.moved-aside DerivedData *.hmap *.ipa # Bundler .bundle Carthage # We recommend against adding the Pods directory to your .gitignore. However # you should judge for yourself, the pros and cons are mentioned at: # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control # # Note: if you ignore the Pods directory, make sure to uncomment # `pod install` in .travis.yml # # Pods/ ================================================ FILE: .travis.yml ================================================ osx_image: xcode9 language: objective-c cache: cocoapods podfile: Example/Podfile env: global: - LANG=en_US.UTF-8 - LC_ALL=en_US.UTF-8 - XCODE_WORKSPACE=Example/FlexBoxLayout.xcworkspace matrix: - SCHEME="FlexBoxLayout_Example" before_install: - gem install xcpretty --no-rdoc --no-ri --no-document --quiet - gem install cocoapods --pre --no-rdoc --no-ri --no-document --quiet - pod install --project-directory=Example script: - set -o pipefail - xcodebuild -workspace "$XCODE_WORKSPACE" -scheme "$SCHEME" -configuration Debug clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcpretty -c - xcodebuild -workspace "$XCODE_WORKSPACE" -scheme "$SCHEME" -configuration Release clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcpretty -c - pod lib lint --allow-warnings after_success: - sleep 3 ================================================ FILE: Example/Example/FBAppDelegate.h ================================================ // // CSSAppDelegate.h // CSSLayout // // Created by qiang.shen on 01/03/2017. // Copyright (c) 2017 qiang.shen. All rights reserved. // @import UIKit; @interface FBAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: Example/Example/FBAppDelegate.m ================================================ // // CSSAppDelegate.m // CSSLayout // // Created by qiang.shen on 01/03/2017. // Copyright (c) 2017 qiang.shen. All rights reserved. // #import "FBAppDelegate.h" @implementation FBAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end ================================================ FILE: Example/Example/FBFPSGraph.h ================================================ // // CSSFPSGraph.h // CSSLayout // // Created by 沈强 on 2017/1/11. // Copyright © 2017年 qiang.shen. All rights reserved. // #import @interface FBFPSGraph : UIView @property (nonatomic, assign, readonly) NSUInteger FPS; @property (nonatomic, assign, readonly) NSUInteger maxFPS; @property (nonatomic, assign, readonly) NSUInteger minFPS; - (instancetype)initWithFrame:(CGRect)frame color:(UIColor *)color; @end ================================================ FILE: Example/Example/FBFPSGraph.m ================================================ // // CSSFPSGraph.m // CSSLayout // // Created by 沈强 on 2017/1/11. // Copyright © 2017年 qiang.shen. All rights reserved. // #import "FBFPSGraph.h" @interface FBFPSGraph() @property (nonatomic, strong, readonly) CAShapeLayer *graph; @property (nonatomic, strong, readonly) UILabel *label; @end @implementation FBFPSGraph { CAShapeLayer *_graph; UILabel *_label; CGFloat *_frames; UIColor *_color; NSTimeInterval _prevTime; NSUInteger _frameCount; NSUInteger _FPS; NSUInteger _maxFPS; NSUInteger _minFPS; NSUInteger _length; NSUInteger _height; CADisplayLink *_uiDisplayLink; // leak to do } - (instancetype)initWithFrame:(CGRect)frame color:(UIColor *)color { if ((self = [super initWithFrame:frame])) { _frameCount = -1; _prevTime = -1; _maxFPS = 0; _minFPS = 60; _length = (NSUInteger)floor(frame.size.width); _height = (NSUInteger)floor(frame.size.height); _frames = calloc(sizeof(CGFloat), _length); _color = color; [self.layer addSublayer:self.graph]; [self addSubview:self.label]; _uiDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onTick:)]; [_uiDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; } return self; } - (void)dealloc { free(_frames); } - (CAShapeLayer *)graph { if (!_graph) { _graph = [CAShapeLayer new]; _graph.frame = self.bounds; _graph.backgroundColor = [_color colorWithAlphaComponent:0.2].CGColor; _graph.fillColor = _color.CGColor; } return _graph; } - (UILabel *)label { if (!_label) { _label = [[UILabel alloc] initWithFrame:self.bounds]; _label.font = [UIFont boldSystemFontOfSize:13]; _label.textAlignment = NSTextAlignmentCenter; } return _label; } - (void)onTick:(CADisplayLink *)uiDisplayLink { NSTimeInterval timestamp = uiDisplayLink.timestamp; _frameCount++; if (_prevTime == -1) { _prevTime = timestamp; } else if (timestamp - _prevTime >= 1) { _FPS = round(_frameCount / (timestamp - _prevTime)); _minFPS = MIN(_minFPS, _FPS); _maxFPS = MAX(_maxFPS, _FPS); dispatch_async(dispatch_get_main_queue(), ^{ self->_label.text = [NSString stringWithFormat:@"%lu", (unsigned long)self->_FPS]; }); CGFloat scale = 60.0 / _height; for (NSUInteger i = 0; i < _length - 1; i++) { _frames[i] = _frames[i + 1]; } _frames[_length - 1] = _FPS / scale; CGMutablePathRef path = CGPathCreateMutable(); CGPathMoveToPoint(path, NULL, 0, _height); for (NSUInteger i = 0; i < _length; i++) { CGPathAddLineToPoint(path, NULL, i, _height - _frames[i]); } CGPathAddLineToPoint(path, NULL, _length - 1, _height); _graph.path = path; CGPathRelease(path); _prevTime = timestamp; _frameCount = 0; } } @end ================================================ FILE: Example/Example/FBFeedModel.h ================================================ // // CSSFeedModel.h // CSSLayout // // Created by 沈强 on 2017/1/11. // Copyright © 2017年 qiang.shen. All rights reserved. // #import @interface FBFeedModel : NSObject - (instancetype)initWithDictionary:(NSDictionary *)dictionary; @property (nonatomic, copy, readonly) NSString *title; @property (nonatomic, copy, readonly) NSString *content; @property (nonatomic, copy, readonly) NSString *username; @property (nonatomic, copy, readonly) NSString *time; @property (nonatomic, copy, readonly) NSString *imageName; @end ================================================ FILE: Example/Example/FBFeedModel.m ================================================ // // CSSFeedModel.m // CSSLayout // // Created by 沈强 on 2017/1/11. // Copyright © 2017年 qiang.shen. All rights reserved. // #import "FBFeedModel.h" @implementation FBFeedModel - (instancetype)initWithDictionary:(NSDictionary *)dictionary { self = super.init; if (self) { _title = dictionary[@"title"]; _content = dictionary[@"content"]; _username = dictionary[@"username"]; _time = dictionary[@"time"]; _imageName = dictionary[@"imageName"]; } return self; } @end ================================================ FILE: Example/Example/FBFeedView.h ================================================ // // CSSFeedView.h // CSSLayout // // Created by 沈强 on 2017/1/11. // Copyright © 2017年 qiang.shen. All rights reserved. // #import #import "FBFeedModel.h" @interface FBFeedView : UIView - (instancetype)initWithModel:(FBFeedModel *)model; @end ================================================ FILE: Example/Example/FBFeedView.m ================================================ // // FBFeedView.m // FBLayout // // Created by 沈强 on 2017/1/11. // Copyright © 2017年 qiang.shen. All rights reserved. // #import "FBFeedView.h" #import "UIView+FBLayout.h" #import "FBLayoutDiv.h" @interface FBFeedView () @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UILabel *contentLabel; @property (nonatomic, strong) UIImageView *contentImageView; @property (nonatomic, strong) UILabel *usernameLabel; @property (nonatomic, strong) UILabel *timeLabel; @end @implementation FBFeedView - (instancetype)initWithModel:(FBFeedModel *)model { if (self = [super initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 0)]) { [self configView]; [self configData:model]; [self layoutView]; } return self; } - (void)configView { _titleLabel = [UILabel new]; [self addSubview:_titleLabel]; _contentLabel = [UILabel new]; [self addSubview:_contentLabel]; _contentLabel.numberOfLines = 0; _contentImageView = [UIImageView new]; _contentImageView.contentMode = UIViewContentModeScaleAspectFit; [self addSubview:_contentImageView]; _usernameLabel = [UILabel new]; [self addSubview:_usernameLabel]; _timeLabel = [UILabel new]; _timeLabel.textAlignment = NSTextAlignmentRight; [self addSubview:_timeLabel]; } - (void)configData:(FBFeedModel *)model { _titleLabel.attributedText = [[NSAttributedString alloc] initWithString:model.title attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:18]}]; _contentLabel.attributedText = [[NSAttributedString alloc] initWithString:model.content attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]}]; _contentImageView.image = [UIImage imageNamed:model.imageName]; _usernameLabel.attributedText = [[NSAttributedString alloc] initWithString:model.username attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]}]; _timeLabel.attributedText = [[NSAttributedString alloc] initWithString:model.time attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12]}]; } - (void)layoutView { [_titleLabel fb_makeLayout:^(FBLayout *layout) { layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)).wrapContent(); }]; [_contentLabel fb_makeLayout:^(FBLayout *layout) { layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)).wrapContent(); }]; [_contentImageView fb_makeLayout:^(FBLayout *layout) { layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)).wrapContent(); }]; [_usernameLabel fb_makeLayout:^(FBLayout *layout) { layout.wrapContent().flexGrow.equalTo(@(1.0)); }]; [_timeLabel fb_makeLayout:^(FBLayout *layout) { layout.wrapContent().flexGrow.equalTo(@(1.0)); }]; FBLayoutDiv *div = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionRow ]; [div fb_makeLayout:^(FBLayout *layout) { layout.flexDirection.equalTo(@(FBFlexDirectionRow)).justifyContent.equalTo(@(FBJustifySpaceBetween)).alignItems.equalTo(@(FBAlignFlexStart)).margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)).children(@[_usernameLabel,_timeLabel]); }]; [self fb_makeLayout:^(FBLayout *layout) { layout.flexDirection.equalTo(@(FBFlexDirectionColumn)).margin.equalToEdgeInsets(UIEdgeInsetsMake(0, 15, 0, 15)).alignItems.equalTo(@(FBAlignFlexStart)).children(@[_titleLabel,_contentLabel,_contentImageView,div]); }]; } @end ================================================ FILE: Example/Example/FBTableViewController.h ================================================ // // CSSTableViewController.h // CSSLayout // // Created by 沈强 on 2017/1/11. // Copyright © 2017年 qiang.shen. All rights reserved. // #import @interface FBTableViewController : UITableViewController @end ================================================ FILE: Example/Example/FBTableViewController.m ================================================ // // FBTableViewController.m // FBLayout // // Created by 沈强 on 2017/1/11. // Copyright © 2017年 qiang.shen. All rights reserved. // #import "FBTableViewController.h" #import "FBFeedModel.h" #import "UITableView+FBLayout.h" #import "FBFeedView.h" #import "FBFPSGraph.h" @interface FBTableViewController () @property(nonatomic, strong)NSMutableArray *feeds; @property(nonatomic, strong)NSMutableArray *sections; @end @implementation FBTableViewController - (void)viewDidLoad { [super viewDidLoad]; UIRefreshControl *refreshControl = [UIRefreshControl new]; [refreshControl addTarget:self action:@selector(refresh) forControlEvents:UIControlEventValueChanged]; self.refreshControl = refreshControl; FBFPSGraph *graph = [[FBFPSGraph alloc] initWithFrame:CGRectMake(0, 20, [UIScreen mainScreen].bounds.size.width, 30) color:[UIColor lightGrayColor]]; [[UIApplication sharedApplication].keyWindow addSubview:graph]; [self loadData]; } - (void)refresh { [self loadData]; [self.refreshControl endRefreshing]; } - (void)loadData { NSString *dataFilePath = [[NSBundle mainBundle] pathForResource:@"data" ofType:@"json"]; NSData *data = [NSData dataWithContentsOfFile:dataFilePath]; NSDictionary *rootDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; NSArray *feedDicts = rootDict[@"feed"]; _feeds = @[].mutableCopy; [feedDicts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [_feeds addObject:[[FBFeedModel alloc] initWithDictionary:obj]]; }]; _sections = [NSMutableArray arrayWithCapacity:1]; [_sections addObject:_feeds]; __weak typeof(self)weakSelf = self; [self.tableView fb_setCellContnetViewBlockForIndexPath:^UIView *(NSIndexPath *indexPath) { return [[FBFeedView alloc]initWithModel:weakSelf.sections[indexPath.section][indexPath.row]]; }]; [self.tableView reloadData]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return _sections.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.sections[section] count]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return [self.tableView fb_heightForIndexPath:indexPath]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { return [self.tableView fb_cellForIndexPath:indexPath]; } #pragma mark - UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row%2==0) { [_sections insertObject:_feeds atIndex:indexPath.section]; [tableView insertSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationLeft]; } else { [_sections removeObjectAtIndex:indexPath.section]; [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationLeft]; } } @end ================================================ FILE: Example/Example/FBViewController.h ================================================ // // CSSViewController.h // CSSLayout // // Created by qiang.shen on 01/03/2017. // Copyright (c) 2017 qiang.shen. All rights reserved. // @import UIKit; @interface FBViewController : UIViewController @end ================================================ FILE: Example/Example/FBViewController.m ================================================ // // FBViewController.m // FBLayout // // Created by qiang.shen on 01/03/2017. // Copyright (c) 2017 qiang.shen. All rights reserved. // #import "FBViewController.h" #import "FlexBoxLayout.h" #import "FBAsyLayoutTransaction.h" @interface FBViewController () @end @implementation FBViewController - (void)viewDidLoad { [super viewDidLoad]; UIScrollView *contentView = [UIScrollView new]; contentView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-44); [self.view addSubview:contentView]; UIView *child1 = [UIView new]; child1.backgroundColor = [UIColor blueColor]; [child1 fb_makeLayout:^(FBLayout *layout) { layout.width.height.equalTo(@100); }]; UIView *child2 = [UIView new]; child2.backgroundColor = [UIColor greenColor]; [child2 fb_makeLayout:^(FBLayout *layout) { layout.equalTo(child1); }]; UILabel *child3 = [UILabel new]; child3.numberOfLines = 0; child3.backgroundColor = [UIColor yellowColor]; [child3 fb_wrapContent]; [child3 setAttributedText:[[NSAttributedString alloc] initWithString:@"testfdsfdsfdsfdsfdsfdsafdsafdsafasdkkk" attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:18]}] ]; [contentView addSubview:child1]; [contentView addSubview:child2]; [contentView addSubview:child3]; FBLayoutDiv *div1 = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn justifyContent:FBJustifySpaceBetween alignItems:FBAlignCenter children:@[child1, child2,child3]]; [div1 fb_makeLayout:^(FBLayout *layout) { layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(20, 0, 0, 0)); layout.width.equalTo(@(150)); }]; UIView *child5 = [UIView new]; child5.backgroundColor = [UIColor blueColor]; [child5 fb_makeLayout:^(FBLayout *layout) { layout.width.height.equalTo(@(50)).margin.equalToEdgeInsets(UIEdgeInsetsMake(0, 0, 10, 0)).flexGrow.equalTo(@1.0); }]; UIView *child6 = [UIView new]; child6.backgroundColor = [UIColor greenColor]; [child6 fb_makeLayout:^(FBLayout *layout) { layout.equalTo(child5); layout.flexGrow.equalTo(@(2.0)); layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 10, 10, 10)); }]; UIView *child7 = [UIView new]; child7.backgroundColor = [UIColor yellowColor]; [child7 fb_makeLayout:^(FBLayout *layout) { layout.equalTo(child5); }]; UIView *child8 = [UIView new]; child8.backgroundColor = [UIColor blackColor]; [child8 fb_makeLayout:^(FBLayout *layout) { layout.equalTo(child5); }]; FBLayoutDiv *div2 =[FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn justifyContent:FBJustifySpaceAround alignItems:FBAlignCenter children:@[child5,child6,child7,child8]]; [div2 fb_makeLayout:^(FBLayout *layout) { layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(20, 0, 0, 0)); layout.width.equalTo(@(150)); }]; [contentView addSubview:child5]; [contentView addSubview:child6]; [contentView addSubview:child7]; [contentView addSubview:child8]; FBLayoutDiv *root = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionRow justifyContent:FBJustifySpaceAround alignItems:FBAlignCenter children:@[div1,div2]]; contentView.fb_contentDiv = root; [root fb_asyApplyLayoutWithSize:[UIScreen mainScreen].bounds.size]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end ================================================ FILE: Example/Example/FlexBoxLayout-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleDisplayName ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1.0 LSRequiresIPhoneOS UILaunchStoryboardName Launch Screen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Example/Example/FlexBoxLayout-Prefix.pch ================================================ // // Prefix header // // The contents of this file are implicitly included at the beginning of every source file. // #import #ifndef __IPHONE_5_0 #warning "This project uses features only available in iOS SDK 5.0 and later." #endif #ifdef __OBJC__ @import UIKit; @import Foundation; #endif ================================================ FILE: Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/Example/Images.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json ================================================ { "images" : [ { "orientation" : "portrait", "idiom" : "iphone", "extent" : "full-screen", "minimum-system-version" : "7.0", "scale" : "2x" }, { "orientation" : "portrait", "idiom" : "iphone", "subtype" : "retina4", "extent" : "full-screen", "minimum-system-version" : "7.0", "scale" : "2x" }, { "orientation" : "portrait", "idiom" : "ipad", "extent" : "full-screen", "minimum-system-version" : "7.0", "scale" : "1x" }, { "orientation" : "landscape", "idiom" : "ipad", "extent" : "full-screen", "minimum-system-version" : "7.0", "scale" : "1x" }, { "orientation" : "portrait", "idiom" : "ipad", "extent" : "full-screen", "minimum-system-version" : "7.0", "scale" : "2x" }, { "orientation" : "landscape", "idiom" : "ipad", "extent" : "full-screen", "minimum-system-version" : "7.0", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/Example/Images.xcassets/breaddoge.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "dogebread.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/Example/Images.xcassets/doge.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "doge@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/Example/Images.xcassets/forkingdog.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "forkingdog@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/Example/Images.xcassets/phil.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "phil.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/Example/Images.xcassets/sark.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "sark@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/Example/Images.xcassets/sinojerk.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "彪哥副本.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/Example/Images.xcassets/sunnyxx.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "下载.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/Example/Launch Screen.storyboard ================================================ ================================================ FILE: Example/Example/Main.storyboard ================================================ ================================================ FILE: Example/Example/data.json ================================================ { "feed": [ { "title": "Hello world", "content": "This is forkingdog team. Here's our logo?\nGithub: \"forkingdog\"", "username": "forkingdog", "time": "2015.04.10", "imageName": "forkingdog" }, { "title": "Team member - sunnyxx", "content": "Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.11", "imageName": "sunnyxx" }, { "title": "Team member - SinoJerk", "content": "Zhidao iOS team, Daifu Tang (aka 彪哥)Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sinojerk", "time": "2015.04.15", "imageName": "sinojerk" }, { "title": "Team member - Phil", "content": "Zhidao iOS team, Jiaqi Guo, Github: philcnWorking at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "phil", "time": "2015.04.15", "imageName": "phil" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1) Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) ", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or tWorking at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了o take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "Hello world", "content": "This is forkingdog team. Here's our logo?\nGithub: \"forkingdog\"", "username": "forkingdog", "time": "2015.04.10", "imageName": "forkingdog" }, { "title": "Team member - sunnyxx", "content": "Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.11", "imageName": "sunnyxx" }, { "title": "Team member - SinoJerk", "content": "Zhidao iOS team, Daifu Tang (aka 彪哥)", "username": "sinojerk", "time": "2015.04.15", "imageName": "sinojerk" }, { "title": "Team member - Phil", "content": "Zhidao iOS team, Jiaqi Guo, Github: philcn", "username": "phil", "time": "2015.04.15", "imageName": "phil" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) ", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) ", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" },{ "title": "Hello world", "content": "This is forkingdog team. Here's our logo?\nGithub: \"forkingdog\"", "username": "forkingdog", "time": "2015.04.10", "imageName": "forkingdog" }, { "title": "Team member - sunnyxx", "content": "Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.11", "imageName": "sunnyxx" }, { "title": "Team member - SinoJerk", "content": "Zhidao iOS team, Daifu Tang (aka 彪哥)", "username": "sinojerk", "time": "2015.04.15", "imageName": "sinojerk" }, { "title": "Team member - Phil", "content": "Zhidao iOS team, Jiaqi Guo, Github: philcn", "username": "phil", "time": "2015.04.15", "imageName": "phil" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) ", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) ", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "Hello world", "content": "This is forkingdog team. Here's our logo?\nGithub: \"forkingdog\"", "username": "forkingdog", "time": "2015.04.10", "imageName": "forkingdog" }, { "title": "Team member - sunnyxx", "content": "Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.11", "imageName": "sunnyxx" }, { "title": "Team member - SinoJerk", "content": "Zhidao iOS team, Daifu Tang (aka 彪哥)Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sinojerk", "time": "2015.04.15", "imageName": "sinojerk" }, { "title": "Team member - Phil", "content": "Zhidao iOS team, Jiaqi Guo, Github: philcnWorking at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "phil", "time": "2015.04.15", "imageName": "phil" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1) Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) ", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or tWorking at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了o take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "Hello world", "content": "This is forkingdog team. Here's our logo?\nGithub: \"forkingdog\"", "username": "forkingdog", "time": "2015.04.10", "imageName": "forkingdog" }, { "title": "Team member - sunnyxx", "content": "Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.11", "imageName": "sunnyxx" }, { "title": "Team member - SinoJerk", "content": "Zhidao iOS team, Daifu Tang (aka 彪哥)", "username": "sinojerk", "time": "2015.04.15", "imageName": "sinojerk" }, { "title": "Team member - Phil", "content": "Zhidao iOS team, Jiaqi Guo, Github: philcn", "username": "phil", "time": "2015.04.15", "imageName": "phil" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) ", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) ", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" },{ "title": "Hello world", "content": "This is forkingdog team. Here's our logo?\nGithub: \"forkingdog\"", "username": "forkingdog", "time": "2015.04.10", "imageName": "forkingdog" }, { "title": "Team member - sunnyxx", "content": "Working at Baidu, Zhidao iOS team, weibo: @我就叫Sunny怎么了", "username": "sunnyxx", "time": "2015.04.11", "imageName": "sunnyxx" }, { "title": "Team member - SinoJerk", "content": "Zhidao iOS team, Daifu Tang (aka 彪哥)", "username": "sinojerk", "time": "2015.04.15", "imageName": "sinojerk" }, { "title": "Team member - Phil", "content": "Zhidao iOS team, Jiaqi Guo, Github: philcn", "username": "phil", "time": "2015.04.15", "imageName": "phil" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) ", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "Good name in man and woman, dear my lord, is the immediate jewel of their souls: Who steals my purse steals trash; ’tis something, nothing. (Othello 3.3) ", "username": "sunnyxx", "time": "2015.04.12", "imageName": "breaddoge" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" }, { "title": "William Shakespeare", "content": "To be, or not to be —that is the question, Whether'tis nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them. To die —to sleep", "username": "sunnyxx", "time": "2015.04.16", "imageName": "" }, { "title": "Sark's bad guy (gay)", "content": "", "username": "sunnyxx", "time": "2015.04.16", "imageName": "sark" }, { "title": "", "content": "Things base and vile, holding no quantity, love can transpose to from and dignity: love looks not with the eyes, but with mind. (A Midsummer Night’s Dream 1.1)", "username": "sunnyxx", "time": "2015.04.17", "imageName": "" } ] } ================================================ FILE: Example/Example/en.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ ================================================ FILE: Example/Example/main.m ================================================ // // main.m // CSSLayout // // Created by qiang.shen on 01/03/2017. // Copyright (c) 2017 qiang.shen. All rights reserved. // @import UIKit; #import "FBAppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([FBAppDelegate class])); } } ================================================ FILE: Example/FlexBoxLayout.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 1B504DC51E699709005F39BA /* data.json in Resources */ = {isa = PBXBuildFile; fileRef = 1B504DAF1E699709005F39BA /* data.json */; }; 1B504DC61E699709005F39BA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1B504DB01E699709005F39BA /* InfoPlist.strings */; }; 1B504DC71E699709005F39BA /* FBAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B504DB31E699709005F39BA /* FBAppDelegate.m */; }; 1B504DC81E699709005F39BA /* FBFeedModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B504DB51E699709005F39BA /* FBFeedModel.m */; }; 1B504DC91E699709005F39BA /* FBFeedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B504DB71E699709005F39BA /* FBFeedView.m */; }; 1B504DCA1E699709005F39BA /* FBFPSGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B504DB91E699709005F39BA /* FBFPSGraph.m */; }; 1B504DCB1E699709005F39BA /* FBTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B504DBB1E699709005F39BA /* FBTableViewController.m */; }; 1B504DCC1E699709005F39BA /* FBViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B504DBD1E699709005F39BA /* FBViewController.m */; }; 1B504DCD1E699709005F39BA /* FlexBoxLayout-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1B504DBE1E699709005F39BA /* FlexBoxLayout-Info.plist */; }; 1B504DCE1E699709005F39BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1B504DC01E699709005F39BA /* Images.xcassets */; }; 1B504DCF1E699709005F39BA /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1B504DC11E699709005F39BA /* Launch Screen.storyboard */; }; 1B504DD01E699709005F39BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B504DC21E699709005F39BA /* main.m */; }; 1B504DD11E699709005F39BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1B504DC31E699709005F39BA /* Main.storyboard */; }; 1B504DD21E699709005F39BA /* show.gif in Resources */ = {isa = PBXBuildFile; fileRef = 1B504DC41E699709005F39BA /* show.gif */; }; 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; }; 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; }; 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; }; B5B68B60067C1C8B9BFFD7F7 /* Pods_FlexBoxLayout_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6764F96706C8B51001BC1C37 /* Pods_FlexBoxLayout_Example.framework */; }; E01EC6B795C9A60747C3FB42 /* Pods_CSSLayout_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28FD6B95245F63FD5FE35E42 /* Pods_CSSLayout_Tests.framework */; }; F3153B8C0BD5351F97BF4F63 /* Pods_FlexBoxLayout_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C49EF148E22F0F64A0AB1B2B /* Pods_FlexBoxLayout_Tests.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6003F582195388D10070C39A /* Project object */; proxyType = 1; remoteGlobalIDString = 6003F589195388D20070C39A; remoteInfo = CSSLayout; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 068C0B79AF1323F8E288905F /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 18D4B89CF6E54D1B702F9867 /* Pods-CSSLayout_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CSSLayout_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-CSSLayout_Example/Pods-CSSLayout_Example.release.xcconfig"; sourceTree = ""; }; 1B504DAF1E699709005F39BA /* data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = data.json; sourceTree = ""; }; 1B504DB11E699709005F39BA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 1B504DB21E699709005F39BA /* FBAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBAppDelegate.h; sourceTree = ""; }; 1B504DB31E699709005F39BA /* FBAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBAppDelegate.m; sourceTree = ""; }; 1B504DB41E699709005F39BA /* FBFeedModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBFeedModel.h; sourceTree = ""; }; 1B504DB51E699709005F39BA /* FBFeedModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBFeedModel.m; sourceTree = ""; }; 1B504DB61E699709005F39BA /* FBFeedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBFeedView.h; sourceTree = ""; }; 1B504DB71E699709005F39BA /* FBFeedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBFeedView.m; sourceTree = ""; }; 1B504DB81E699709005F39BA /* FBFPSGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBFPSGraph.h; sourceTree = ""; }; 1B504DB91E699709005F39BA /* FBFPSGraph.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBFPSGraph.m; sourceTree = ""; }; 1B504DBA1E699709005F39BA /* FBTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBTableViewController.h; sourceTree = ""; }; 1B504DBB1E699709005F39BA /* FBTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBTableViewController.m; sourceTree = ""; }; 1B504DBC1E699709005F39BA /* FBViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBViewController.h; sourceTree = ""; }; 1B504DBD1E699709005F39BA /* FBViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBViewController.m; sourceTree = ""; }; 1B504DBE1E699709005F39BA /* FlexBoxLayout-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "FlexBoxLayout-Info.plist"; sourceTree = ""; }; 1B504DBF1E699709005F39BA /* FlexBoxLayout-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FlexBoxLayout-Prefix.pch"; sourceTree = ""; }; 1B504DC01E699709005F39BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 1B504DC11E699709005F39BA /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; 1B504DC21E699709005F39BA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 1B504DC31E699709005F39BA /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 1B504DC41E699709005F39BA /* show.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = show.gif; sourceTree = ""; }; 28FD6B95245F63FD5FE35E42 /* Pods_CSSLayout_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CSSLayout_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 292FC21B24FA1B08B43F517C /* Pods-CSSLayout_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CSSLayout_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CSSLayout_Tests/Pods-CSSLayout_Tests.release.xcconfig"; sourceTree = ""; }; 3212EEC1552C4000D2191436 /* Pods-FlexBoxLayout_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlexBoxLayout_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example.release.xcconfig"; sourceTree = ""; }; 52EC424DC9D27ECAAB290F40 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 6003F58A195388D20070C39A /* FlexBoxLayout_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FlexBoxLayout_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 6003F5AE195388D20070C39A /* FlexBoxLayout_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FlexBoxLayout_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; }; 6764F96706C8B51001BC1C37 /* Pods_FlexBoxLayout_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FlexBoxLayout_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6D099FB4ACC9803FF52C67AC /* FlexBoxLayout.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = FlexBoxLayout.podspec; path = ../FlexBoxLayout.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; A0D4C00CEF45E50075D739C6 /* Pods-FlexBoxLayout_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlexBoxLayout_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example.debug.xcconfig"; sourceTree = ""; }; B7A0145C4CAFFE471C48D6A1 /* Pods-CSSLayout_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CSSLayout_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CSSLayout_Tests/Pods-CSSLayout_Tests.debug.xcconfig"; sourceTree = ""; }; B9CF66F3893828F1349FC4B1 /* Pods-FlexBoxLayout_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlexBoxLayout_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests.release.xcconfig"; sourceTree = ""; }; C49EF148E22F0F64A0AB1B2B /* Pods_FlexBoxLayout_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FlexBoxLayout_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CF9E9E0911EE83E18A2B68D7 /* Pods-CSSLayout_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CSSLayout_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CSSLayout_Example/Pods-CSSLayout_Example.debug.xcconfig"; sourceTree = ""; }; D6DC2FE7479FD607DCE17A8F /* Pods_CSSLayout_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CSSLayout_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DFFCD98910AFEBDEE9B4188D /* Pods-FlexBoxLayout_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlexBoxLayout_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 6003F587195388D20070C39A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, B5B68B60067C1C8B9BFFD7F7 /* Pods_FlexBoxLayout_Example.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 6003F5AB195388D20070C39A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, E01EC6B795C9A60747C3FB42 /* Pods_CSSLayout_Tests.framework in Frameworks */, F3153B8C0BD5351F97BF4F63 /* Pods_FlexBoxLayout_Tests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 1B504DAE1E699709005F39BA /* Example */ = { isa = PBXGroup; children = ( 1B504DAF1E699709005F39BA /* data.json */, 1B504DB01E699709005F39BA /* InfoPlist.strings */, 1B504DB21E699709005F39BA /* FBAppDelegate.h */, 1B504DB31E699709005F39BA /* FBAppDelegate.m */, 1B504DB41E699709005F39BA /* FBFeedModel.h */, 1B504DB51E699709005F39BA /* FBFeedModel.m */, 1B504DB61E699709005F39BA /* FBFeedView.h */, 1B504DB71E699709005F39BA /* FBFeedView.m */, 1B504DB81E699709005F39BA /* FBFPSGraph.h */, 1B504DB91E699709005F39BA /* FBFPSGraph.m */, 1B504DBA1E699709005F39BA /* FBTableViewController.h */, 1B504DBB1E699709005F39BA /* FBTableViewController.m */, 1B504DBC1E699709005F39BA /* FBViewController.h */, 1B504DBD1E699709005F39BA /* FBViewController.m */, 1B504DBE1E699709005F39BA /* FlexBoxLayout-Info.plist */, 1B504DBF1E699709005F39BA /* FlexBoxLayout-Prefix.pch */, 1B504DC01E699709005F39BA /* Images.xcassets */, 1B504DC11E699709005F39BA /* Launch Screen.storyboard */, 1B504DC21E699709005F39BA /* main.m */, 1B504DC31E699709005F39BA /* Main.storyboard */, 1B504DC41E699709005F39BA /* show.gif */, ); path = Example; sourceTree = ""; }; 5CAF783DFE8EA55D73A1D59A /* Pods */ = { isa = PBXGroup; children = ( CF9E9E0911EE83E18A2B68D7 /* Pods-CSSLayout_Example.debug.xcconfig */, 18D4B89CF6E54D1B702F9867 /* Pods-CSSLayout_Example.release.xcconfig */, B7A0145C4CAFFE471C48D6A1 /* Pods-CSSLayout_Tests.debug.xcconfig */, 292FC21B24FA1B08B43F517C /* Pods-CSSLayout_Tests.release.xcconfig */, A0D4C00CEF45E50075D739C6 /* Pods-FlexBoxLayout_Example.debug.xcconfig */, 3212EEC1552C4000D2191436 /* Pods-FlexBoxLayout_Example.release.xcconfig */, DFFCD98910AFEBDEE9B4188D /* Pods-FlexBoxLayout_Tests.debug.xcconfig */, B9CF66F3893828F1349FC4B1 /* Pods-FlexBoxLayout_Tests.release.xcconfig */, ); name = Pods; sourceTree = ""; }; 6003F581195388D10070C39A = { isa = PBXGroup; children = ( 1B504DAE1E699709005F39BA /* Example */, 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, 6003F5B5195388D20070C39A /* Tests */, 6003F58C195388D20070C39A /* Frameworks */, 6003F58B195388D20070C39A /* Products */, 5CAF783DFE8EA55D73A1D59A /* Pods */, ); sourceTree = ""; }; 6003F58B195388D20070C39A /* Products */ = { isa = PBXGroup; children = ( 6003F58A195388D20070C39A /* FlexBoxLayout_Example.app */, 6003F5AE195388D20070C39A /* FlexBoxLayout_Tests.xctest */, ); name = Products; sourceTree = ""; }; 6003F58C195388D20070C39A /* Frameworks */ = { isa = PBXGroup; children = ( 6003F58D195388D20070C39A /* Foundation.framework */, 6003F58F195388D20070C39A /* CoreGraphics.framework */, 6003F591195388D20070C39A /* UIKit.framework */, 6003F5AF195388D20070C39A /* XCTest.framework */, D6DC2FE7479FD607DCE17A8F /* Pods_CSSLayout_Example.framework */, 28FD6B95245F63FD5FE35E42 /* Pods_CSSLayout_Tests.framework */, 6764F96706C8B51001BC1C37 /* Pods_FlexBoxLayout_Example.framework */, C49EF148E22F0F64A0AB1B2B /* Pods_FlexBoxLayout_Tests.framework */, ); name = Frameworks; sourceTree = ""; }; 6003F5B5195388D20070C39A /* Tests */ = { isa = PBXGroup; children = ( 6003F5BB195388D20070C39A /* Tests.m */, 6003F5B6195388D20070C39A /* Supporting Files */, ); path = Tests; sourceTree = ""; }; 6003F5B6195388D20070C39A /* Supporting Files */ = { isa = PBXGroup; children = ( 6003F5B7195388D20070C39A /* Tests-Info.plist */, 6003F5B8195388D20070C39A /* InfoPlist.strings */, 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */, ); name = "Supporting Files"; sourceTree = ""; }; 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { isa = PBXGroup; children = ( 6D099FB4ACC9803FF52C67AC /* FlexBoxLayout.podspec */, 52EC424DC9D27ECAAB290F40 /* README.md */, 068C0B79AF1323F8E288905F /* LICENSE */, ); name = "Podspec Metadata"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 6003F589195388D20070C39A /* FlexBoxLayout_Example */ = { isa = PBXNativeTarget; buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "FlexBoxLayout_Example" */; buildPhases = ( 6E87588D0023C9959A95585D /* [CP] Check Pods Manifest.lock */, 6003F586195388D20070C39A /* Sources */, 6003F587195388D20070C39A /* Frameworks */, 6003F588195388D20070C39A /* Resources */, D494E9B8BDEC1BCE97924FAB /* [CP] Embed Pods Frameworks */, 14D4A1F23C16937E0215CE0C /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = FlexBoxLayout_Example; productName = CSSLayout; productReference = 6003F58A195388D20070C39A /* FlexBoxLayout_Example.app */; productType = "com.apple.product-type.application"; }; 6003F5AD195388D20070C39A /* FlexBoxLayout_Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "FlexBoxLayout_Tests" */; buildPhases = ( 030B1D524966A6889A2B17B6 /* [CP] Check Pods Manifest.lock */, 6003F5AA195388D20070C39A /* Sources */, 6003F5AB195388D20070C39A /* Frameworks */, 6003F5AC195388D20070C39A /* Resources */, D8B3D3976E30337C85147C8B /* [CP] Embed Pods Frameworks */, 907FAE99B5F337A286DB306C /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 6003F5B4195388D20070C39A /* PBXTargetDependency */, ); name = FlexBoxLayout_Tests; productName = CSSLayoutTests; productReference = 6003F5AE195388D20070C39A /* FlexBoxLayout_Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 6003F582195388D10070C39A /* Project object */ = { isa = PBXProject; attributes = { CLASSPREFIX = CSS; LastUpgradeCheck = 0810; ORGANIZATIONNAME = qiang.shen; TargetAttributes = { 6003F589195388D20070C39A = { DevelopmentTeam = CNS46A8385; }; 6003F5AD195388D20070C39A = { LastSwiftMigration = 0810; TestTargetID = 6003F589195388D20070C39A; }; }; }; buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "FlexBoxLayout" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 6003F581195388D10070C39A; productRefGroup = 6003F58B195388D20070C39A /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 6003F589195388D20070C39A /* FlexBoxLayout_Example */, 6003F5AD195388D20070C39A /* FlexBoxLayout_Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 6003F588195388D20070C39A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 1B504DCD1E699709005F39BA /* FlexBoxLayout-Info.plist in Resources */, 1B504DCE1E699709005F39BA /* Images.xcassets in Resources */, 1B504DC51E699709005F39BA /* data.json in Resources */, 1B504DD11E699709005F39BA /* Main.storyboard in Resources */, 1B504DCF1E699709005F39BA /* Launch Screen.storyboard in Resources */, 1B504DD21E699709005F39BA /* show.gif in Resources */, 1B504DC61E699709005F39BA /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 6003F5AC195388D20070C39A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 030B1D524966A6889A2B17B6 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-FlexBoxLayout_Tests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 14D4A1F23C16937E0215CE0C /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example-resources.sh\"\n"; showEnvVarsInLog = 0; }; 6E87588D0023C9959A95585D /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-FlexBoxLayout_Example-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 907FAE99B5F337A286DB306C /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests-resources.sh\"\n"; showEnvVarsInLog = 0; }; D494E9B8BDEC1BCE97924FAB /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example-frameworks.sh", "${BUILT_PRODUCTS_DIR}/FlexBoxLayout/FlexBoxLayout.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FlexBoxLayout.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; D8B3D3976E30337C85147C8B /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 6003F586195388D20070C39A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 1B504DC91E699709005F39BA /* FBFeedView.m in Sources */, 1B504DCB1E699709005F39BA /* FBTableViewController.m in Sources */, 1B504DCC1E699709005F39BA /* FBViewController.m in Sources */, 1B504DC71E699709005F39BA /* FBAppDelegate.m in Sources */, 1B504DCA1E699709005F39BA /* FBFPSGraph.m in Sources */, 1B504DD01E699709005F39BA /* main.m in Sources */, 1B504DC81E699709005F39BA /* FBFeedModel.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 6003F5AA195388D20070C39A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 6003F5BC195388D20070C39A /* Tests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 6003F589195388D20070C39A /* FlexBoxLayout_Example */; targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ 1B504DB01E699709005F39BA /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 1B504DB11E699709005F39BA /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; 6003F5B8195388D20070C39A /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 6003F5B9195388D20070C39A /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 6003F5BD195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 6003F5BE195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 6003F5C0195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = A0D4C00CEF45E50075D739C6 /* Pods-FlexBoxLayout_Example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; DEVELOPMENT_TEAM = CNS46A8385; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Example/FlexBoxLayout-Prefix.pch"; INFOPLIST_FILE = "$(SRCROOT)/Example/FlexBoxLayout-Info.plist"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = 1; WRAPPER_EXTENSION = app; }; name = Debug; }; 6003F5C1195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 3212EEC1552C4000D2191436 /* Pods-FlexBoxLayout_Example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; DEVELOPMENT_TEAM = CNS46A8385; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Example/FlexBoxLayout-Prefix.pch"; INFOPLIST_FILE = "$(SRCROOT)/Example/FlexBoxLayout-Info.plist"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = 1; WRAPPER_EXTENSION = app; }; name = Release; }; 6003F5C3195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = DFFCD98910AFEBDEE9B4188D /* Pods-FlexBoxLayout_Tests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = "Tests/Tests-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FlexBoxLayout_Example.app/FlexBoxLayout_Example"; WRAPPER_EXTENSION = xctest; }; name = Debug; }; 6003F5C4195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = B9CF66F3893828F1349FC4B1 /* Pods-FlexBoxLayout_Tests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; INFOPLIST_FILE = "Tests/Tests-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FlexBoxLayout_Example.app/FlexBoxLayout_Example"; WRAPPER_EXTENSION = xctest; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 6003F585195388D10070C39A /* Build configuration list for PBXProject "FlexBoxLayout" */ = { isa = XCConfigurationList; buildConfigurations = ( 6003F5BD195388D20070C39A /* Debug */, 6003F5BE195388D20070C39A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "FlexBoxLayout_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( 6003F5C0195388D20070C39A /* Debug */, 6003F5C1195388D20070C39A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "FlexBoxLayout_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 6003F5C3195388D20070C39A /* Debug */, 6003F5C4195388D20070C39A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 6003F582195388D10070C39A /* Project object */; } ================================================ FILE: Example/FlexBoxLayout.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Example/FlexBoxLayout.xcodeproj/xcshareddata/xcschemes/FlexBoxLayout_Example.xcscheme ================================================ ================================================ FILE: Example/FlexBoxLayout.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Example/Podfile ================================================ use_frameworks! target 'FlexBoxLayout_Example' do pod 'FlexBoxLayout', :path => '../' target 'FlexBoxLayout_Tests' do inherit! :search_paths end end ================================================ FILE: Example/Pods/Local Podspecs/CSSLayout.podspec.json ================================================ { "name": "CSSLayout", "version": "0.1.0", "summary": "A short description of CSSLayout.", "description": "TODO: Add long description of the pod here.", "homepage": "https://github.com//CSSLayout", "license": { "type": "MIT", "file": "LICENSE" }, "authors": { "qiang.shen": "qiang..shen@ele.me" }, "source": { "git": "https://github.com//CSSLayout.git", "tag": "0.1.0" }, "platforms": { "ios": "8.0" }, "source_files": "CSSLayout/Classes/**/*" } ================================================ FILE: Example/Pods/Local Podspecs/FlexBoxLayout.podspec.json ================================================ { "name": "FlexBoxLayout", "version": "0.8.0", "summary": "iOS Flexbox layout", "description": "iOS Flexbox layout.", "homepage": "https://github.com/LPD-iOS/FlexBoxLayout", "license": { "type": "MIT", "file": "LICENSE" }, "authors": { "qiang.shen": "qiang..shen@ele.me" }, "source": { "git": "https://github.com/LPD-iOS/FlexBoxLayout.git", "tag": "0.8.0" }, "platforms": { "ios": "7.0" }, "source_files": "FlexBoxLayout/Classes/**/*" } ================================================ FILE: Example/Pods/Pods.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 074281F10B4BD032C759D5E027979F25 /* UIScrollView+FBLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = A679FAD04E34D2928A10E6EF7D8E654A /* UIScrollView+FBLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0AFB39D1C712985A6DF7A6AA4452FDAF /* UIView+FBLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = F2AD820207A75360574CEAADD230F65F /* UIView+FBLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12E761460A9A1A30D9D2D4282325CC60 /* Yoga.h in Headers */ = {isa = PBXBuildFile; fileRef = A287CB6AFC514232A851E69344B0C197 /* Yoga.h */; settings = {ATTRIBUTES = (Public, ); }; }; 160DBAF5EEC188CC905C78225949E46A /* UIView+CellStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = A1956BA50EDC91A59FA37AFE95186638 /* UIView+CellStyle.m */; }; 1E4075A62064FD9E005E2E283403B23B /* Pods-FlexBoxLayout_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E66EE03D48B624AC02A2B49D889D5A /* Pods-FlexBoxLayout_Tests-dummy.m */; }; 223110F99A8EB144E28C7A448594E7CE /* FBLayoutDiv.h in Headers */ = {isa = PBXBuildFile; fileRef = 23C0BD45B3C29027EE7A49BF1279DDD1 /* FBLayoutDiv.h */; settings = {ATTRIBUTES = (Public, ); }; }; 24A20B48A74554EAF8D4E651EA114EB2 /* UIView+CellStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A8E86EEE8799A1D99189FC3BEA7C81D /* UIView+CellStyle.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27796ECDA59185A953DA0FFA57B7F25E /* FBLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = E02AD018C1A71AE618C53C4B1C8567D2 /* FBLayout.m */; }; 27C50BB61366FC186DBEF19F8B5619CA /* FBLayoutDiv.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C389877D7EC3455CB33481430658905 /* FBLayoutDiv.m */; }; 28B81C6B1EA79390B8C3D00389EE1354 /* FBAsyLayoutTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = C86831EFE6EA0D9F5004DA92522F13A1 /* FBAsyLayoutTransaction.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2AF7B3DD54EC7C69B3414BE68F98CB1F /* FBLayout+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = FD83157240386FD10108EF2B8E81763A /* FBLayout+Private.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2E213AAA3CF36ED57D275F7332CE8121 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */; }; 332BB3A134C141A3847282116ADBD7B8 /* Pods-FlexBoxLayout_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 46DA683DCAD78388835833164C99E397 /* Pods-FlexBoxLayout_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3941FB3BA6FDE9ED9310749F8F22BD15 /* FBAsyLayoutTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = EF09C7361790D94CDDE0B1849DB46774 /* FBAsyLayoutTransaction.m */; }; 44AAFAB497B669E871FCB7C57EE29340 /* UIScrollView+FBLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 625814E8687BD6E4CCBE9617FC149010 /* UIScrollView+FBLayout.m */; }; 47A387E0F410A35C50BFBC6C5FCC8F91 /* UITableView+FBLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = CE1FC63FC96981D06A3145050F77B1FA /* UITableView+FBLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 496E51C79E3311FFB35B9CC79B7F32F0 /* FBViewLayoutCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 140E720A6BF95DEFE96A0AFA0EF78466 /* FBViewLayoutCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; 59463ECB80BD00322BEB10F9118C339A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */; }; 5F3AC3EB714F932B822F6D52882C98A6 /* Yoga.c in Sources */ = {isa = PBXBuildFile; fileRef = E2242E03251D75704DA9C06CA859A2A6 /* Yoga.c */; }; 624F5C60A91E1EA916CE7B86CE8974B9 /* YGEnums.h in Headers */ = {isa = PBXBuildFile; fileRef = 4477E26F28167791E966128D63112285 /* YGEnums.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7A5BC9B29458BB3F9C97970198337558 /* UIView+FBLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 275F2A9FE9B427666D1BC31E1F8F69CF /* UIView+FBLayout.m */; }; 9A3DDC6F730C6543869415D12A458769 /* FlexBoxLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 05C23A869CC871BC17105D506FCE81A5 /* FlexBoxLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; A41191AF6702A33307CA6D7DC494C35B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */; }; B144BB144F3C840B2F389A2BBF7D990E /* YGNodeList.c in Sources */ = {isa = PBXBuildFile; fileRef = 6A0685EC7AE20051150BD74E405C9385 /* YGNodeList.c */; }; B6810986A273F9F4E7A31FDA9176FDCE /* FBViewLayoutCache.m in Sources */ = {isa = PBXBuildFile; fileRef = A5BA61E51C24B927D535BB0A3E250E07 /* FBViewLayoutCache.m */; }; BB0682994A5FE52268169DED0E68FEF3 /* YGMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F91BE6DCC560C47418328E24F7FB966 /* YGMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; BB926D7643C5657CA0DCB0B2DF2BD0D5 /* FlexBoxLayout-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D24416D14C30E5B422EFBDF4D4C68F20 /* FlexBoxLayout-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; BD01BBB9FF61C08AE7806A1B19A5E037 /* Pods-FlexBoxLayout_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D8B3565582A311827EF5F4F6CBF3C79 /* Pods-FlexBoxLayout_Example-dummy.m */; }; D2988A2D09C135F5E062AA9CF6CAF29B /* FBLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 8238C5AA11691DC26D6C024915641692 /* FBLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; D4267BA56BFD5B6CCF6917C701D3E3AD /* FlexBoxLayout-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C4D1F5DC7482CA5B3D588FCB9BBEA7F /* FlexBoxLayout-dummy.m */; }; DF49D00F0E322A434FF3AE3D03863C26 /* YGNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = ED7026F42D6CE0E7CAEFACC393F767C2 /* YGNodeList.h */; settings = {ATTRIBUTES = (Public, ); }; }; ED7582975465F2BD5D259CAB10565680 /* FBLayoutProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = FF938746E92980E48A2B78703D1D331A /* FBLayoutProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; F4331388A47E6E0B3623F132669DCA7E /* Pods-FlexBoxLayout_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 13F5D17844E15E7CD0244F2747C114B7 /* Pods-FlexBoxLayout_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; F5B7D7A943DC0A8E664CE4ADB8F7E589 /* UITableView+FBLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FA68351A46C44F004B29A026C21F1F7 /* UITableView+FBLayout.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 5E31603E08815CFCF061BF7F7E2C48FB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 41E766C7E18FD317438ED40FF82DC6DC; remoteInfo = FlexBoxLayout; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 05C23A869CC871BC17105D506FCE81A5 /* FlexBoxLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FlexBoxLayout.h; path = FlexBoxLayout/Classes/FlexBoxLayout.h; sourceTree = ""; }; 0F84B9E8D4A7A28998EF57C13810232E /* FlexBoxLayout-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FlexBoxLayout-prefix.pch"; sourceTree = ""; }; 13F5D17844E15E7CD0244F2747C114B7 /* Pods-FlexBoxLayout_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-FlexBoxLayout_Tests-umbrella.h"; sourceTree = ""; }; 140E720A6BF95DEFE96A0AFA0EF78466 /* FBViewLayoutCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FBViewLayoutCache.h; sourceTree = ""; }; 1EB5B3A0601897C638905921C4E93709 /* FlexBoxLayout.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FlexBoxLayout.xcconfig; sourceTree = ""; }; 1FE6805B5D87366AFBDEFD27C98B290C /* FlexBoxLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FlexBoxLayout.framework; path = FlexBoxLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 23C0BD45B3C29027EE7A49BF1279DDD1 /* FBLayoutDiv.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FBLayoutDiv.h; sourceTree = ""; }; 275F2A9FE9B427666D1BC31E1F8F69CF /* UIView+FBLayout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "UIView+FBLayout.m"; sourceTree = ""; }; 290E94BD29A9DCB9680BE35E94C6BD1A /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 2D8B3565582A311827EF5F4F6CBF3C79 /* Pods-FlexBoxLayout_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-FlexBoxLayout_Example-dummy.m"; sourceTree = ""; }; 2FD39294095E485283D8B39CC890D5B0 /* Pods-FlexBoxLayout_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FlexBoxLayout_Tests.debug.xcconfig"; sourceTree = ""; }; 30E66EE03D48B624AC02A2B49D889D5A /* Pods-FlexBoxLayout_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-FlexBoxLayout_Tests-dummy.m"; sourceTree = ""; }; 37398D34E653DF09A2641D1FF0379F93 /* Pods-FlexBoxLayout_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-FlexBoxLayout_Tests.modulemap"; sourceTree = ""; }; 3920D39DA60C0E0A54E725A375A9D2F2 /* Pods-FlexBoxLayout_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-FlexBoxLayout_Example-acknowledgements.markdown"; sourceTree = ""; }; 39EE870E022521F916CF1735D3872A9B /* Pods-FlexBoxLayout_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FlexBoxLayout_Example.debug.xcconfig"; sourceTree = ""; }; 3C4D1F5DC7482CA5B3D588FCB9BBEA7F /* FlexBoxLayout-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FlexBoxLayout-dummy.m"; sourceTree = ""; }; 4477E26F28167791E966128D63112285 /* YGEnums.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = YGEnums.h; sourceTree = ""; }; 46DA683DCAD78388835833164C99E397 /* Pods-FlexBoxLayout_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-FlexBoxLayout_Example-umbrella.h"; sourceTree = ""; }; 4D5C5564506559994F56953653C0597F /* Pods-FlexBoxLayout_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FlexBoxLayout_Tests-acknowledgements.plist"; sourceTree = ""; }; 4F91BE6DCC560C47418328E24F7FB966 /* YGMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = YGMacros.h; sourceTree = ""; }; 5291E0156247D0EA2FE84C4F847DA894 /* Pods_FlexBoxLayout_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_FlexBoxLayout_Example.framework; path = "Pods-FlexBoxLayout_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 625814E8687BD6E4CCBE9617FC149010 /* UIScrollView+FBLayout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+FBLayout.m"; sourceTree = ""; }; 65F0519680CAC7157DD162A4BDAB8174 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 6A0685EC7AE20051150BD74E405C9385 /* YGNodeList.c */ = {isa = PBXFileReference; includeInIndex = 1; path = YGNodeList.c; sourceTree = ""; }; 6C389877D7EC3455CB33481430658905 /* FBLayoutDiv.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FBLayoutDiv.m; sourceTree = ""; }; 7C918EAC464D825B50D7323CE03CCBF4 /* Pods_FlexBoxLayout_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_FlexBoxLayout_Tests.framework; path = "Pods-FlexBoxLayout_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 7D3E316A89DC03F48CC0478DBD27BB54 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 8238C5AA11691DC26D6C024915641692 /* FBLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FBLayout.h; sourceTree = ""; }; 87BD2A5B371E05B87DD42D2F9C51F1BB /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 97CF82D77B31C1A8057CE4673BB62703 /* Pods-FlexBoxLayout_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-FlexBoxLayout_Example.modulemap"; sourceTree = ""; }; 9A8E86EEE8799A1D99189FC3BEA7C81D /* UIView+CellStyle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "UIView+CellStyle.h"; sourceTree = ""; }; 9CDD81E16FD57D9D94A4D625CAB6D1DD /* Pods-FlexBoxLayout_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-FlexBoxLayout_Tests-frameworks.sh"; sourceTree = ""; }; 9FA68351A46C44F004B29A026C21F1F7 /* UITableView+FBLayout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "UITableView+FBLayout.m"; sourceTree = ""; }; A1956BA50EDC91A59FA37AFE95186638 /* UIView+CellStyle.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "UIView+CellStyle.m"; sourceTree = ""; }; A257B3145A7378ADE9EDED5C87D424B3 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A287CB6AFC514232A851E69344B0C197 /* Yoga.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = Yoga.h; sourceTree = ""; }; A5BA61E51C24B927D535BB0A3E250E07 /* FBViewLayoutCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FBViewLayoutCache.m; sourceTree = ""; }; A679FAD04E34D2928A10E6EF7D8E654A /* UIScrollView+FBLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+FBLayout.h"; sourceTree = ""; }; A6AA8261A684BEDB4E39DE0039FB7CFE /* Pods-FlexBoxLayout_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FlexBoxLayout_Example.release.xcconfig"; sourceTree = ""; }; B5C67F5EB53D0F1E5B9F1D9AB04E04EB /* Pods-FlexBoxLayout_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FlexBoxLayout_Tests.release.xcconfig"; sourceTree = ""; }; BB2F23F43464233B16E4949A84AC95FF /* FlexBoxLayout.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FlexBoxLayout.modulemap; sourceTree = ""; }; C5AEE383861D5A321567B20E0DA7DCFF /* FlexBoxLayout.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; path = FlexBoxLayout.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; C86831EFE6EA0D9F5004DA92522F13A1 /* FBAsyLayoutTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FBAsyLayoutTransaction.h; sourceTree = ""; }; CB76AF194B7D41D72CE4E18A95B9B1BB /* Pods-FlexBoxLayout_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-FlexBoxLayout_Example-resources.sh"; sourceTree = ""; }; CE1FC63FC96981D06A3145050F77B1FA /* UITableView+FBLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "UITableView+FBLayout.h"; sourceTree = ""; }; D24416D14C30E5B422EFBDF4D4C68F20 /* FlexBoxLayout-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FlexBoxLayout-umbrella.h"; sourceTree = ""; }; E02AD018C1A71AE618C53C4B1C8567D2 /* FBLayout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FBLayout.m; sourceTree = ""; }; E2242E03251D75704DA9C06CA859A2A6 /* Yoga.c */ = {isa = PBXFileReference; includeInIndex = 1; path = Yoga.c; sourceTree = ""; }; E3DE20A64A10DBA2666AADEB69FBDF4A /* Pods-FlexBoxLayout_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FlexBoxLayout_Example-acknowledgements.plist"; sourceTree = ""; }; E4FEC2EDF454AA9E1DEFECFC0060C086 /* Pods-FlexBoxLayout_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-FlexBoxLayout_Example-frameworks.sh"; sourceTree = ""; }; E864CCF1865050B90A4A04C700A1BF2B /* Pods-FlexBoxLayout_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-FlexBoxLayout_Tests-resources.sh"; sourceTree = ""; }; EA975E06D68410FD07A0D83CE44DD0CA /* Pods-FlexBoxLayout_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-FlexBoxLayout_Tests-acknowledgements.markdown"; sourceTree = ""; }; ED7026F42D6CE0E7CAEFACC393F767C2 /* YGNodeList.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = YGNodeList.h; sourceTree = ""; }; EF09C7361790D94CDDE0B1849DB46774 /* FBAsyLayoutTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FBAsyLayoutTransaction.m; sourceTree = ""; }; F2AD820207A75360574CEAADD230F65F /* UIView+FBLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "UIView+FBLayout.h"; sourceTree = ""; }; FD83157240386FD10108EF2B8E81763A /* FBLayout+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FBLayout+Private.h"; sourceTree = ""; }; FF938746E92980E48A2B78703D1D331A /* FBLayoutProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FBLayoutProtocol.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 1F70E0C3CC5AB54430581C29B9DB3557 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 59463ECB80BD00322BEB10F9118C339A /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 20907C3C1F5F687ADE94307647D71B49 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 2E213AAA3CF36ED57D275F7332CE8121 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 51B04F0E9B2F8FE4D1C2CBFBE195CDDD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( A41191AF6702A33307CA6D7DC494C35B /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 37104CB29296EE749DD0E511C13A0258 /* Pods-FlexBoxLayout_Tests */ = { isa = PBXGroup; children = ( 7D3E316A89DC03F48CC0478DBD27BB54 /* Info.plist */, 37398D34E653DF09A2641D1FF0379F93 /* Pods-FlexBoxLayout_Tests.modulemap */, EA975E06D68410FD07A0D83CE44DD0CA /* Pods-FlexBoxLayout_Tests-acknowledgements.markdown */, 4D5C5564506559994F56953653C0597F /* Pods-FlexBoxLayout_Tests-acknowledgements.plist */, 30E66EE03D48B624AC02A2B49D889D5A /* Pods-FlexBoxLayout_Tests-dummy.m */, 9CDD81E16FD57D9D94A4D625CAB6D1DD /* Pods-FlexBoxLayout_Tests-frameworks.sh */, E864CCF1865050B90A4A04C700A1BF2B /* Pods-FlexBoxLayout_Tests-resources.sh */, 13F5D17844E15E7CD0244F2747C114B7 /* Pods-FlexBoxLayout_Tests-umbrella.h */, 2FD39294095E485283D8B39CC890D5B0 /* Pods-FlexBoxLayout_Tests.debug.xcconfig */, B5C67F5EB53D0F1E5B9F1D9AB04E04EB /* Pods-FlexBoxLayout_Tests.release.xcconfig */, ); name = "Pods-FlexBoxLayout_Tests"; path = "Target Support Files/Pods-FlexBoxLayout_Tests"; sourceTree = ""; }; 38054A9669674D6DB29CCAFE6E019ABE /* Targets Support Files */ = { isa = PBXGroup; children = ( A163D21F3C14EC053751B53B96BBBED2 /* Pods-FlexBoxLayout_Example */, 37104CB29296EE749DD0E511C13A0258 /* Pods-FlexBoxLayout_Tests */, ); name = "Targets Support Files"; sourceTree = ""; }; 3A001529011D65E856D14B1DF3138AEE /* FlexBoxLayout */ = { isa = PBXGroup; children = ( 05C23A869CC871BC17105D506FCE81A5 /* FlexBoxLayout.h */, C14E2F523D91CC4AEB2552CF247C0DDC /* Component */, C296628F770D87195ADB5A65057CC92E /* Layout */, 4F4BAD4647F62685EEBBEEC3F651A741 /* Pod */, 460D842DB85BA12AEC6D1C32ECBE10DE /* Support Files */, B857249BE921C5798FDDF7C7C5C78278 /* Transaction */, ); name = FlexBoxLayout; path = ../..; sourceTree = ""; }; 460D842DB85BA12AEC6D1C32ECBE10DE /* Support Files */ = { isa = PBXGroup; children = ( BB2F23F43464233B16E4949A84AC95FF /* FlexBoxLayout.modulemap */, 1EB5B3A0601897C638905921C4E93709 /* FlexBoxLayout.xcconfig */, 3C4D1F5DC7482CA5B3D588FCB9BBEA7F /* FlexBoxLayout-dummy.m */, 0F84B9E8D4A7A28998EF57C13810232E /* FlexBoxLayout-prefix.pch */, D24416D14C30E5B422EFBDF4D4C68F20 /* FlexBoxLayout-umbrella.h */, 290E94BD29A9DCB9680BE35E94C6BD1A /* Info.plist */, ); name = "Support Files"; path = "Example/Pods/Target Support Files/FlexBoxLayout"; sourceTree = ""; }; 4F4BAD4647F62685EEBBEEC3F651A741 /* Pod */ = { isa = PBXGroup; children = ( C5AEE383861D5A321567B20E0DA7DCFF /* FlexBoxLayout.podspec */, 87BD2A5B371E05B87DD42D2F9C51F1BB /* LICENSE */, 65F0519680CAC7157DD162A4BDAB8174 /* README.md */, ); name = Pod; sourceTree = ""; }; 63CC4F4786802208A2635642B9C9F344 /* Development Pods */ = { isa = PBXGroup; children = ( 3A001529011D65E856D14B1DF3138AEE /* FlexBoxLayout */, ); name = "Development Pods"; sourceTree = ""; }; 7D31310903384B719B78AD21D8A19623 /* Products */ = { isa = PBXGroup; children = ( 1FE6805B5D87366AFBDEFD27C98B290C /* FlexBoxLayout.framework */, 5291E0156247D0EA2FE84C4F847DA894 /* Pods_FlexBoxLayout_Example.framework */, 7C918EAC464D825B50D7323CE03CCBF4 /* Pods_FlexBoxLayout_Tests.framework */, ); name = Products; sourceTree = ""; }; 7DB346D0F39D3F0E887471402A8071AB = { isa = PBXGroup; children = ( 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 63CC4F4786802208A2635642B9C9F344 /* Development Pods */, BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, 7D31310903384B719B78AD21D8A19623 /* Products */, 38054A9669674D6DB29CCAFE6E019ABE /* Targets Support Files */, ); sourceTree = ""; }; A163D21F3C14EC053751B53B96BBBED2 /* Pods-FlexBoxLayout_Example */ = { isa = PBXGroup; children = ( A257B3145A7378ADE9EDED5C87D424B3 /* Info.plist */, 97CF82D77B31C1A8057CE4673BB62703 /* Pods-FlexBoxLayout_Example.modulemap */, 3920D39DA60C0E0A54E725A375A9D2F2 /* Pods-FlexBoxLayout_Example-acknowledgements.markdown */, E3DE20A64A10DBA2666AADEB69FBDF4A /* Pods-FlexBoxLayout_Example-acknowledgements.plist */, 2D8B3565582A311827EF5F4F6CBF3C79 /* Pods-FlexBoxLayout_Example-dummy.m */, E4FEC2EDF454AA9E1DEFECFC0060C086 /* Pods-FlexBoxLayout_Example-frameworks.sh */, CB76AF194B7D41D72CE4E18A95B9B1BB /* Pods-FlexBoxLayout_Example-resources.sh */, 46DA683DCAD78388835833164C99E397 /* Pods-FlexBoxLayout_Example-umbrella.h */, 39EE870E022521F916CF1735D3872A9B /* Pods-FlexBoxLayout_Example.debug.xcconfig */, A6AA8261A684BEDB4E39DE0039FB7CFE /* Pods-FlexBoxLayout_Example.release.xcconfig */, ); name = "Pods-FlexBoxLayout_Example"; path = "Target Support Files/Pods-FlexBoxLayout_Example"; sourceTree = ""; }; B857249BE921C5798FDDF7C7C5C78278 /* Transaction */ = { isa = PBXGroup; children = ( C86831EFE6EA0D9F5004DA92522F13A1 /* FBAsyLayoutTransaction.h */, EF09C7361790D94CDDE0B1849DB46774 /* FBAsyLayoutTransaction.m */, ); name = Transaction; path = FlexBoxLayout/Classes/Transaction; sourceTree = ""; }; BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { isa = PBXGroup; children = ( D35AF013A5F0BAD4F32504907A52519E /* iOS */, ); name = Frameworks; sourceTree = ""; }; C14E2F523D91CC4AEB2552CF247C0DDC /* Component */ = { isa = PBXGroup; children = ( 23C0BD45B3C29027EE7A49BF1279DDD1 /* FBLayoutDiv.h */, 6C389877D7EC3455CB33481430658905 /* FBLayoutDiv.m */, A679FAD04E34D2928A10E6EF7D8E654A /* UIScrollView+FBLayout.h */, 625814E8687BD6E4CCBE9617FC149010 /* UIScrollView+FBLayout.m */, CE1FC63FC96981D06A3145050F77B1FA /* UITableView+FBLayout.h */, 9FA68351A46C44F004B29A026C21F1F7 /* UITableView+FBLayout.m */, 9A8E86EEE8799A1D99189FC3BEA7C81D /* UIView+CellStyle.h */, A1956BA50EDC91A59FA37AFE95186638 /* UIView+CellStyle.m */, F2AD820207A75360574CEAADD230F65F /* UIView+FBLayout.h */, 275F2A9FE9B427666D1BC31E1F8F69CF /* UIView+FBLayout.m */, ); name = Component; path = FlexBoxLayout/Classes/Component; sourceTree = ""; }; C296628F770D87195ADB5A65057CC92E /* Layout */ = { isa = PBXGroup; children = ( 8238C5AA11691DC26D6C024915641692 /* FBLayout.h */, E02AD018C1A71AE618C53C4B1C8567D2 /* FBLayout.m */, FD83157240386FD10108EF2B8E81763A /* FBLayout+Private.h */, FF938746E92980E48A2B78703D1D331A /* FBLayoutProtocol.h */, 140E720A6BF95DEFE96A0AFA0EF78466 /* FBViewLayoutCache.h */, A5BA61E51C24B927D535BB0A3E250E07 /* FBViewLayoutCache.m */, 4477E26F28167791E966128D63112285 /* YGEnums.h */, 4F91BE6DCC560C47418328E24F7FB966 /* YGMacros.h */, 6A0685EC7AE20051150BD74E405C9385 /* YGNodeList.c */, ED7026F42D6CE0E7CAEFACC393F767C2 /* YGNodeList.h */, E2242E03251D75704DA9C06CA859A2A6 /* Yoga.c */, A287CB6AFC514232A851E69344B0C197 /* Yoga.h */, ); name = Layout; path = FlexBoxLayout/Classes/Layout; sourceTree = ""; }; D35AF013A5F0BAD4F32504907A52519E /* iOS */ = { isa = PBXGroup; children = ( 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */, ); name = iOS; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 10AE11C6EF074FFE4FC01375B1D42720 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 332BB3A134C141A3847282116ADBD7B8 /* Pods-FlexBoxLayout_Example-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; C19564AB2046B740FB73F9A5046C1279 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 28B81C6B1EA79390B8C3D00389EE1354 /* FBAsyLayoutTransaction.h in Headers */, 2AF7B3DD54EC7C69B3414BE68F98CB1F /* FBLayout+Private.h in Headers */, D2988A2D09C135F5E062AA9CF6CAF29B /* FBLayout.h in Headers */, 223110F99A8EB144E28C7A448594E7CE /* FBLayoutDiv.h in Headers */, ED7582975465F2BD5D259CAB10565680 /* FBLayoutProtocol.h in Headers */, 496E51C79E3311FFB35B9CC79B7F32F0 /* FBViewLayoutCache.h in Headers */, BB926D7643C5657CA0DCB0B2DF2BD0D5 /* FlexBoxLayout-umbrella.h in Headers */, 9A3DDC6F730C6543869415D12A458769 /* FlexBoxLayout.h in Headers */, 074281F10B4BD032C759D5E027979F25 /* UIScrollView+FBLayout.h in Headers */, 47A387E0F410A35C50BFBC6C5FCC8F91 /* UITableView+FBLayout.h in Headers */, 24A20B48A74554EAF8D4E651EA114EB2 /* UIView+CellStyle.h in Headers */, 0AFB39D1C712985A6DF7A6AA4452FDAF /* UIView+FBLayout.h in Headers */, 624F5C60A91E1EA916CE7B86CE8974B9 /* YGEnums.h in Headers */, BB0682994A5FE52268169DED0E68FEF3 /* YGMacros.h in Headers */, DF49D00F0E322A434FF3AE3D03863C26 /* YGNodeList.h in Headers */, 12E761460A9A1A30D9D2D4282325CC60 /* Yoga.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; F8E777C7FEFBF8E45EA9ABD311ADBBD2 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( F4331388A47E6E0B3623F132669DCA7E /* Pods-FlexBoxLayout_Tests-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 1B22BBF88589FB9ADEAD498EBDE7C031 /* Pods-FlexBoxLayout_Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 2490DC59C5CB413E3D391C08E5196B9D /* Build configuration list for PBXNativeTarget "Pods-FlexBoxLayout_Tests" */; buildPhases = ( A18364E17DE4B83F94617A60DF55ED8B /* Sources */, 20907C3C1F5F687ADE94307647D71B49 /* Frameworks */, F8E777C7FEFBF8E45EA9ABD311ADBBD2 /* Headers */, ); buildRules = ( ); dependencies = ( ); name = "Pods-FlexBoxLayout_Tests"; productName = "Pods-FlexBoxLayout_Tests"; productReference = 7C918EAC464D825B50D7323CE03CCBF4 /* Pods_FlexBoxLayout_Tests.framework */; productType = "com.apple.product-type.framework"; }; 41E766C7E18FD317438ED40FF82DC6DC /* FlexBoxLayout */ = { isa = PBXNativeTarget; buildConfigurationList = 6174DFF5875A6EBB2BD2091D40B956E6 /* Build configuration list for PBXNativeTarget "FlexBoxLayout" */; buildPhases = ( ED40EBE9D1514753BB9FBF1F08E96914 /* Sources */, 51B04F0E9B2F8FE4D1C2CBFBE195CDDD /* Frameworks */, C19564AB2046B740FB73F9A5046C1279 /* Headers */, ); buildRules = ( ); dependencies = ( ); name = FlexBoxLayout; productName = FlexBoxLayout; productReference = 1FE6805B5D87366AFBDEFD27C98B290C /* FlexBoxLayout.framework */; productType = "com.apple.product-type.framework"; }; 5849EAFB406116E302285CD12144D699 /* Pods-FlexBoxLayout_Example */ = { isa = PBXNativeTarget; buildConfigurationList = 701DD7E99E02ADF946D22BBF87013F6D /* Build configuration list for PBXNativeTarget "Pods-FlexBoxLayout_Example" */; buildPhases = ( F8DBD786FD72536A00CF88895BAF64F3 /* Sources */, 1F70E0C3CC5AB54430581C29B9DB3557 /* Frameworks */, 10AE11C6EF074FFE4FC01375B1D42720 /* Headers */, ); buildRules = ( ); dependencies = ( 509FAA5EAA7D6FA7B40B312A745D6A41 /* PBXTargetDependency */, ); name = "Pods-FlexBoxLayout_Example"; productName = "Pods-FlexBoxLayout_Example"; productReference = 5291E0156247D0EA2FE84C4F847DA894 /* Pods_FlexBoxLayout_Example.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0930; LastUpgradeCheck = 0930; }; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 7DB346D0F39D3F0E887471402A8071AB; productRefGroup = 7D31310903384B719B78AD21D8A19623 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 41E766C7E18FD317438ED40FF82DC6DC /* FlexBoxLayout */, 5849EAFB406116E302285CD12144D699 /* Pods-FlexBoxLayout_Example */, 1B22BBF88589FB9ADEAD498EBDE7C031 /* Pods-FlexBoxLayout_Tests */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ A18364E17DE4B83F94617A60DF55ED8B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 1E4075A62064FD9E005E2E283403B23B /* Pods-FlexBoxLayout_Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; ED40EBE9D1514753BB9FBF1F08E96914 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 3941FB3BA6FDE9ED9310749F8F22BD15 /* FBAsyLayoutTransaction.m in Sources */, 27796ECDA59185A953DA0FFA57B7F25E /* FBLayout.m in Sources */, 27C50BB61366FC186DBEF19F8B5619CA /* FBLayoutDiv.m in Sources */, B6810986A273F9F4E7A31FDA9176FDCE /* FBViewLayoutCache.m in Sources */, D4267BA56BFD5B6CCF6917C701D3E3AD /* FlexBoxLayout-dummy.m in Sources */, 44AAFAB497B669E871FCB7C57EE29340 /* UIScrollView+FBLayout.m in Sources */, F5B7D7A943DC0A8E664CE4ADB8F7E589 /* UITableView+FBLayout.m in Sources */, 160DBAF5EEC188CC905C78225949E46A /* UIView+CellStyle.m in Sources */, 7A5BC9B29458BB3F9C97970198337558 /* UIView+FBLayout.m in Sources */, B144BB144F3C840B2F389A2BBF7D990E /* YGNodeList.c in Sources */, 5F3AC3EB714F932B822F6D52882C98A6 /* Yoga.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; F8DBD786FD72536A00CF88895BAF64F3 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( BD01BBB9FF61C08AE7806A1B19A5E037 /* Pods-FlexBoxLayout_Example-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 509FAA5EAA7D6FA7B40B312A745D6A41 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = FlexBoxLayout; target = 41E766C7E18FD317438ED40FF82DC6DC /* FlexBoxLayout */; targetProxy = 5E31603E08815CFCF061BF7F7E2C48FB /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 1A0C0A7C5EEA03C1264BF39264B9A1AF /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 1EB5B3A0601897C638905921C4E93709 /* FlexBoxLayout.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; GCC_PREFIX_HEADER = "Target Support Files/FlexBoxLayout/FlexBoxLayout-prefix.pch"; INFOPLIST_FILE = "Target Support Files/FlexBoxLayout/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/FlexBoxLayout/FlexBoxLayout.modulemap"; PRODUCT_NAME = FlexBoxLayout; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 1C3ED16E144B9A188CC88F2343EB3B4F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGNING_REQUIRED = NO; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_RELEASE=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; STRIP_INSTALLED_PRODUCT = NO; SYMROOT = "${SRCROOT}/../build"; }; name = Release; }; 51F393FE91B4B6C835FB4B238187AD09 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGNING_REQUIRED = NO; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_DEBUG=1", "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; STRIP_INSTALLED_PRODUCT = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SYMROOT = "${SRCROOT}/../build"; }; name = Debug; }; 5AE04C30A73E2FAD0C6BF002269C0C4F /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = B5C67F5EB53D0F1E5B9F1D9AB04E04EB /* Pods-FlexBoxLayout_Tests.release.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-FlexBoxLayout_Tests/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = Pods_FlexBoxLayout_Tests; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 84CA01D401CEDB5622D9AA58ADB02E04 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 1EB5B3A0601897C638905921C4E93709 /* FlexBoxLayout.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; GCC_PREFIX_HEADER = "Target Support Files/FlexBoxLayout/FlexBoxLayout-prefix.pch"; INFOPLIST_FILE = "Target Support Files/FlexBoxLayout/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/FlexBoxLayout/FlexBoxLayout.modulemap"; PRODUCT_NAME = FlexBoxLayout; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; A092433A2097F141B00BE81560909598 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 39EE870E022521F916CF1735D3872A9B /* Pods-FlexBoxLayout_Example.debug.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-FlexBoxLayout_Example/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = Pods_FlexBoxLayout_Example; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; CF037B089A147420760A7C4B0B2014C3 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = A6AA8261A684BEDB4E39DE0039FB7CFE /* Pods-FlexBoxLayout_Example.release.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-FlexBoxLayout_Example/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = Pods_FlexBoxLayout_Example; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; E2D7E675F5062300126497067201F979 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 2FD39294095E485283D8B39CC890D5B0 /* Pods-FlexBoxLayout_Tests.debug.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-FlexBoxLayout_Tests/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = Pods_FlexBoxLayout_Tests; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 2490DC59C5CB413E3D391C08E5196B9D /* Build configuration list for PBXNativeTarget "Pods-FlexBoxLayout_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( E2D7E675F5062300126497067201F979 /* Debug */, 5AE04C30A73E2FAD0C6BF002269C0C4F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( 51F393FE91B4B6C835FB4B238187AD09 /* Debug */, 1C3ED16E144B9A188CC88F2343EB3B4F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6174DFF5875A6EBB2BD2091D40B956E6 /* Build configuration list for PBXNativeTarget "FlexBoxLayout" */ = { isa = XCConfigurationList; buildConfigurations = ( 1A0C0A7C5EEA03C1264BF39264B9A1AF /* Debug */, 84CA01D401CEDB5622D9AA58ADB02E04 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 701DD7E99E02ADF946D22BBF87013F6D /* Build configuration list for PBXNativeTarget "Pods-FlexBoxLayout_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( A092433A2097F141B00BE81560909598 /* Debug */, CF037B089A147420760A7C4B0B2014C3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; } ================================================ FILE: Example/Pods/Target Support Files/FlexBoxLayout/FlexBoxLayout-dummy.m ================================================ #import @interface PodsDummy_FlexBoxLayout : NSObject @end @implementation PodsDummy_FlexBoxLayout @end ================================================ FILE: Example/Pods/Target Support Files/FlexBoxLayout/FlexBoxLayout-prefix.pch ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif ================================================ FILE: Example/Pods/Target Support Files/FlexBoxLayout/FlexBoxLayout-umbrella.h ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif #import "FBLayoutDiv.h" #import "UIScrollView+FBLayout.h" #import "UITableView+FBLayout.h" #import "UIView+CellStyle.h" #import "UIView+FBLayout.h" #import "FlexBoxLayout.h" #import "FBLayout+Private.h" #import "FBLayout.h" #import "FBLayoutProtocol.h" #import "FBViewLayoutCache.h" #import "YGEnums.h" #import "YGMacros.h" #import "YGNodeList.h" #import "Yoga.h" #import "FBAsyLayoutTransaction.h" FOUNDATION_EXPORT double FlexBoxLayoutVersionNumber; FOUNDATION_EXPORT const unsigned char FlexBoxLayoutVersionString[]; ================================================ FILE: Example/Pods/Target Support Files/FlexBoxLayout/FlexBoxLayout.modulemap ================================================ framework module FlexBoxLayout { umbrella header "FlexBoxLayout-umbrella.h" export * module * { export * } } ================================================ FILE: Example/Pods/Target Support Files/FlexBoxLayout/FlexBoxLayout.xcconfig ================================================ CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FlexBoxLayout GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} SKIP_INSTALL = YES ================================================ FILE: Example/Pods/Target Support Files/FlexBoxLayout/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 0.8.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 1.0.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example-acknowledgements.markdown ================================================ # Acknowledgements This application makes use of the following third party libraries: ## FlexBoxLayout Copyright (c) 2017 qiang.shen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Generated by CocoaPods - https://cocoapods.org ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example-acknowledgements.plist ================================================ PreferenceSpecifiers FooterText This application makes use of the following third party libraries: Title Acknowledgements Type PSGroupSpecifier FooterText Copyright (c) 2017 qiang.shen <qiang..shen@ele.me> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. License MIT Title FlexBoxLayout Type PSGroupSpecifier FooterText Generated by CocoaPods - https://cocoapods.org Title Type PSGroupSpecifier StringsTable Acknowledgements Title Acknowledgements ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example-dummy.m ================================================ #import @interface PodsDummy_Pods_FlexBoxLayout_Example : NSObject @end @implementation PodsDummy_Pods_FlexBoxLayout_Example @end ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example-frameworks.sh ================================================ #!/bin/sh set -e echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" # Used as a return value for each invocation of `strip_invalid_archs` function. STRIP_BINARY_RETVAL=0 # This protects against multiple targets copying the same framework dependency at the same time. The solution # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") # Copies and strips a vendored framework install_framework() { if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then local source="${BUILT_PRODUCTS_DIR}/$1" elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" elif [ -r "$1" ]; then local source="$1" fi local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" if [ -L "${source}" ]; then echo "Symlinked..." source="$(readlink "${source}")" fi # Use filter instead of exclude so missing patterns don't throw errors. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" local basename basename="$(basename -s .framework "$1")" binary="${destination}/${basename}.framework/${basename}" if ! [ -r "$binary" ]; then binary="${destination}/${basename}" fi # Strip invalid architectures so "fat" simulator / device frameworks work on device if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then strip_invalid_archs "$binary" fi # Resign the code if required by the build settings to avoid unstable apps code_sign_if_enabled "${destination}/$(basename "$1")" # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then local swift_runtime_libs swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) for lib in $swift_runtime_libs; do echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" code_sign_if_enabled "${destination}/${lib}" done fi } # Copies and strips a vendored dSYM install_dsym() { local source="$1" if [ -r "$source" ]; then # Copy the dSYM into a the targets temp dir. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" local basename basename="$(basename -s .framework.dSYM "$source")" binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" # Strip invalid architectures so "fat" simulator / device frameworks work on device if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then strip_invalid_archs "$binary" fi if [[ $STRIP_BINARY_RETVAL == 1 ]]; then # Move the stripped file into its final destination. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" else # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" fi fi } # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then # Use the current code_sign_identitiy echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then code_sign_cmd="$code_sign_cmd &" fi echo "$code_sign_cmd" eval "$code_sign_cmd" fi } # Strip invalid architectures strip_invalid_archs() { binary="$1" # Get architectures for current target binary binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" # Intersect them with the architectures we are building for intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" # If there are no archs supported by this binary then warn the user if [[ -z "$intersected_archs" ]]; then echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." STRIP_BINARY_RETVAL=0 return fi stripped="" for arch in $binary_archs; do if ! [[ "${ARCHS}" == *"$arch"* ]]; then # Strip non-valid architectures in-place lipo -remove "$arch" -output "$binary" "$binary" || exit 1 stripped="$stripped $arch" fi done if [[ "$stripped" ]]; then echo "Stripped $binary of architectures:$stripped" fi STRIP_BINARY_RETVAL=1 } if [[ "$CONFIGURATION" == "Debug" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/FlexBoxLayout/FlexBoxLayout.framework" fi if [[ "$CONFIGURATION" == "Release" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/FlexBoxLayout/FlexBoxLayout.framework" fi if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then wait fi ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example-resources.sh ================================================ #!/bin/sh set -e mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt > "$RESOURCES_TO_COPY" XCASSET_FILES=() # This protects against multiple targets copying the same framework dependency at the same time. The solution # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") case "${TARGETED_DEVICE_FAMILY}" in 1,2) TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" ;; 1) TARGET_DEVICE_ARGS="--target-device iphone" ;; 2) TARGET_DEVICE_ARGS="--target-device ipad" ;; 3) TARGET_DEVICE_ARGS="--target-device tv" ;; 4) TARGET_DEVICE_ARGS="--target-device watch" ;; *) TARGET_DEVICE_ARGS="--target-device mac" ;; esac install_resource() { if [[ "$1" = /* ]] ; then RESOURCE_PATH="$1" else RESOURCE_PATH="${PODS_ROOT}/$1" fi if [[ ! -e "$RESOURCE_PATH" ]] ; then cat << EOM error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. EOM exit 1 fi case $RESOURCE_PATH in *.storyboard) echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.xib) echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.framework) echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" ;; *.xcdatamodel) echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" ;; *.xcdatamodeld) echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" ;; *.xcmappingmodel) echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" ;; *.xcassets) ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") ;; *) echo "$RESOURCE_PATH" || true echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" ;; esac } mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" fi rm -f "$RESOURCES_TO_COPY" if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] then # Find all other xcassets (this unfortunately includes those of path pods and other targets). OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) while read line; do if [[ $line != "${PODS_ROOT}*" ]]; then XCASSET_FILES+=("$line") fi done <<<"$OTHER_XCASSETS" printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" fi ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example-umbrella.h ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif FOUNDATION_EXPORT double Pods_FlexBoxLayout_ExampleVersionNumber; FOUNDATION_EXPORT const unsigned char Pods_FlexBoxLayout_ExampleVersionString[]; ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example.debug.xcconfig ================================================ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FlexBoxLayout" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FlexBoxLayout/FlexBoxLayout.framework/Headers" OTHER_LDFLAGS = $(inherited) -framework "FlexBoxLayout" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example.modulemap ================================================ framework module Pods_FlexBoxLayout_Example { umbrella header "Pods-FlexBoxLayout_Example-umbrella.h" export * module * { export * } } ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Example/Pods-FlexBoxLayout_Example.release.xcconfig ================================================ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FlexBoxLayout" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FlexBoxLayout/FlexBoxLayout.framework/Headers" OTHER_LDFLAGS = $(inherited) -framework "FlexBoxLayout" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 1.0.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests-acknowledgements.markdown ================================================ # Acknowledgements This application makes use of the following third party libraries: Generated by CocoaPods - https://cocoapods.org ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests-acknowledgements.plist ================================================ PreferenceSpecifiers FooterText This application makes use of the following third party libraries: Title Acknowledgements Type PSGroupSpecifier FooterText Generated by CocoaPods - https://cocoapods.org Title Type PSGroupSpecifier StringsTable Acknowledgements Title Acknowledgements ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests-dummy.m ================================================ #import @interface PodsDummy_Pods_FlexBoxLayout_Tests : NSObject @end @implementation PodsDummy_Pods_FlexBoxLayout_Tests @end ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests-frameworks.sh ================================================ #!/bin/sh set -e echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" # Used as a return value for each invocation of `strip_invalid_archs` function. STRIP_BINARY_RETVAL=0 # This protects against multiple targets copying the same framework dependency at the same time. The solution # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") # Copies and strips a vendored framework install_framework() { if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then local source="${BUILT_PRODUCTS_DIR}/$1" elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" elif [ -r "$1" ]; then local source="$1" fi local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" if [ -L "${source}" ]; then echo "Symlinked..." source="$(readlink "${source}")" fi # Use filter instead of exclude so missing patterns don't throw errors. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" local basename basename="$(basename -s .framework "$1")" binary="${destination}/${basename}.framework/${basename}" if ! [ -r "$binary" ]; then binary="${destination}/${basename}" fi # Strip invalid architectures so "fat" simulator / device frameworks work on device if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then strip_invalid_archs "$binary" fi # Resign the code if required by the build settings to avoid unstable apps code_sign_if_enabled "${destination}/$(basename "$1")" # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then local swift_runtime_libs swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) for lib in $swift_runtime_libs; do echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" code_sign_if_enabled "${destination}/${lib}" done fi } # Copies and strips a vendored dSYM install_dsym() { local source="$1" if [ -r "$source" ]; then # Copy the dSYM into a the targets temp dir. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" local basename basename="$(basename -s .framework.dSYM "$source")" binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" # Strip invalid architectures so "fat" simulator / device frameworks work on device if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then strip_invalid_archs "$binary" fi if [[ $STRIP_BINARY_RETVAL == 1 ]]; then # Move the stripped file into its final destination. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" else # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" fi fi } # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then # Use the current code_sign_identitiy echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then code_sign_cmd="$code_sign_cmd &" fi echo "$code_sign_cmd" eval "$code_sign_cmd" fi } # Strip invalid architectures strip_invalid_archs() { binary="$1" # Get architectures for current target binary binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" # Intersect them with the architectures we are building for intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" # If there are no archs supported by this binary then warn the user if [[ -z "$intersected_archs" ]]; then echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." STRIP_BINARY_RETVAL=0 return fi stripped="" for arch in $binary_archs; do if ! [[ "${ARCHS}" == *"$arch"* ]]; then # Strip non-valid architectures in-place lipo -remove "$arch" -output "$binary" "$binary" || exit 1 stripped="$stripped $arch" fi done if [[ "$stripped" ]]; then echo "Stripped $binary of architectures:$stripped" fi STRIP_BINARY_RETVAL=1 } if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then wait fi ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests-resources.sh ================================================ #!/bin/sh set -e mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt > "$RESOURCES_TO_COPY" XCASSET_FILES=() # This protects against multiple targets copying the same framework dependency at the same time. The solution # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") case "${TARGETED_DEVICE_FAMILY}" in 1,2) TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" ;; 1) TARGET_DEVICE_ARGS="--target-device iphone" ;; 2) TARGET_DEVICE_ARGS="--target-device ipad" ;; 3) TARGET_DEVICE_ARGS="--target-device tv" ;; 4) TARGET_DEVICE_ARGS="--target-device watch" ;; *) TARGET_DEVICE_ARGS="--target-device mac" ;; esac install_resource() { if [[ "$1" = /* ]] ; then RESOURCE_PATH="$1" else RESOURCE_PATH="${PODS_ROOT}/$1" fi if [[ ! -e "$RESOURCE_PATH" ]] ; then cat << EOM error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. EOM exit 1 fi case $RESOURCE_PATH in *.storyboard) echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.xib) echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.framework) echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" ;; *.xcdatamodel) echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" ;; *.xcdatamodeld) echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" ;; *.xcmappingmodel) echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" ;; *.xcassets) ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") ;; *) echo "$RESOURCE_PATH" || true echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" ;; esac } mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" fi rm -f "$RESOURCES_TO_COPY" if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] then # Find all other xcassets (this unfortunately includes those of path pods and other targets). OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) while read line; do if [[ $line != "${PODS_ROOT}*" ]]; then XCASSET_FILES+=("$line") fi done <<<"$OTHER_XCASSETS" printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" fi ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests-umbrella.h ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif FOUNDATION_EXPORT double Pods_FlexBoxLayout_TestsVersionNumber; FOUNDATION_EXPORT const unsigned char Pods_FlexBoxLayout_TestsVersionString[]; ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests.debug.xcconfig ================================================ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FlexBoxLayout" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FlexBoxLayout/FlexBoxLayout.framework/Headers" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests.modulemap ================================================ framework module Pods_FlexBoxLayout_Tests { umbrella header "Pods-FlexBoxLayout_Tests-umbrella.h" export * module * { export * } } ================================================ FILE: Example/Pods/Target Support Files/Pods-FlexBoxLayout_Tests/Pods-FlexBoxLayout_Tests.release.xcconfig ================================================ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FlexBoxLayout" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FlexBoxLayout/FlexBoxLayout.framework/Headers" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods ================================================ FILE: Example/Tests/Tests-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Example/Tests/Tests-Prefix.pch ================================================ // The contents of this file are implicitly included at the beginning of every test case source file. #ifdef __OBJC__ @import FBSnapshotTestCase; #endif ================================================ FILE: Example/Tests/Tests.m ================================================ // // CSSLayoutTests.m // CSSLayoutTests // // Created by qiang.shen on 01/03/2017. // Copyright (c) 2017 qiang.shen. All rights reserved. // @import XCTest; @interface Tests : XCTestCase @end @implementation Tests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testExample { XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); } @end ================================================ FILE: Example/Tests/en.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ ================================================ FILE: FlexBoxLayout/Assets/.gitkeep ================================================ ================================================ FILE: FlexBoxLayout/Classes/Component/FBLayoutDiv.h ================================================ // // FBLayoutSpec.h // CSJSView // // Created by 沈强 on 2016/12/23. // Copyright © 2016年 沈强. All rights reserved. // #import #import "FBLayoutProtocol.h" NS_ASSUME_NONNULL_BEGIN /** FBLayoutDiv is virtual view, split view to a different area, avoid too much view. */ @interface FBLayoutDiv : NSObject @property(nonatomic)CGRect frame; + (instancetype)layoutDivWithFlexDirection:(FBFlexDirection)direction; + (instancetype)layoutDivWithFlexDirection:(FBFlexDirection)direction justifyContent:(FBJustify)justifyContent alignItems:(FBAlign)alignItems children:(NSArray>*)children; @end NS_ASSUME_NONNULL_END ================================================ FILE: FlexBoxLayout/Classes/Component/FBLayoutDiv.m ================================================ // // FBLayoutSpec.m // CSJSView // // Created by 沈强 on 2016/12/23. // Copyright © 2016年 沈强. All rights reserved. // #import "FBLayoutDiv.h" #import "FBAsyLayoutTransaction.h" @interface FBLayoutDiv(){ NSMutableArray *_fb_children; NSDictionary *_fbStyles; } @property(nonatomic, strong) FBLayout *fb_layout; @end @implementation FBLayoutDiv @dynamic fb_children; - (instancetype)init { if (self = [super init]) { _fb_layout = [FBLayout new]; _fb_layout.context = self; _fb_children = [NSMutableArray array]; } return self; } - (void)setFbStyles:(NSDictionary *)fbStyles { _fbStyles = fbStyles; _fb_layout.fbStyles = fbStyles; } - (NSDictionary *)fbStyles { return _fbStyles; } + (instancetype)layoutDivWithFlexDirection:(FBFlexDirection)direction { FBLayoutDiv *layoutDiv = [self new]; [layoutDiv fb_makeLayout:^(FBLayout *layout) { [layout setFlexDirection:direction]; }]; return layoutDiv; } + (instancetype)layoutDivWithFlexDirection:(FBFlexDirection)direction justifyContent:(FBJustify)justifyContent alignItems:(FBAlign)alignItems children:(NSArray >*)children { FBLayoutDiv *layoutDiv = [self new]; [layoutDiv fb_makeLayout:^(FBLayout *layout) { [layout setFlexDirection:direction]; [layout setJustifyContent:justifyContent]; [layout setAlignItems:alignItems]; }]; [layoutDiv setFb_children:children]; return layoutDiv; } #pragma mark - children - (void)setFb_children:(NSArray >*)children { if (_fb_children == children) { return; } _fb_children = [children mutableCopy]; [_fb_layout removeAllChildren]; for (id layoutElement in _fb_children) { NSAssert([layoutElement conformsToProtocol:NSProtocolFromString(@"FBLayoutProtocol")], @"child %@ has no conformsToProtocol FBLayoutProtocol", self); [_fb_layout addChild:layoutElement.fb_layout]; } } - (void)fb_addChild:(id)layout { NSAssert([layout conformsToProtocol:NSProtocolFromString(@"FBLayoutProtocol")], @"child %@ has no conformsToProtocol FBLayoutProtocol", self); NSMutableArray *newChildren = [[self fb_children] mutableCopy]; [newChildren addObject:layout]; self.fb_children = newChildren; } - (void)fb_addChildren:(NSArray> *)children { NSMutableArray *newChildren = [[self fb_children] mutableCopy]; [newChildren addObjectsFromArray:children]; self.fb_children = newChildren; } - (void)fb_insertChild:(id)layout atIndex:(NSInteger)index { NSAssert([layout conformsToProtocol:NSProtocolFromString(@"FBLayoutProtocol")], @"child %@ has no conformsToProtocol FBLayoutProtocol", self); NSMutableArray *newChildren = [[self fb_children] mutableCopy]; [newChildren insertObject:layout atIndex:index]; self.fb_children = newChildren; } - (id)fb_childLayoutAtIndex:(NSUInteger)index { return [self.fb_children objectAtIndex:index]; } - (void)fb_removeChild:(id)layout { NSMutableArray *newChildren = [[self fb_children] mutableCopy]; [newChildren removeObject:layout]; self.fb_children = newChildren; } - (void)fb_removeAllChildren { self.fb_children = nil; } - (NSArray *)fb_children { return [_fb_children copy]; } - (CGRect)frame { return _frame; } - (FBLayout *)fb_makeLayout:(void(^)(FBLayout *layout))layout { if (layout) { layout([self fb_layout]); } return [self fb_layout]; } #pragma mark - layout - (void)fb_applyLayouWithSize:(CGSize)size { [_fb_layout calculateLayoutWithSize:size]; _frame = _fb_layout.frame; [self fb_applyLayoutToViewHierachy]; } - (void)fb_asyApplyLayoutWithSize:(CGSize)size { [FBAsyLayoutTransaction addCalculateTransaction:^{ [_fb_layout calculateLayoutWithSize:size]; } complete:^{ _frame = _fb_layout.frame; [self fb_applyLayoutToViewHierachy]; }]; } - (void)fb_applyLayoutToViewHierachy { for (id layoutElement in _fb_children) { layoutElement.frame = (CGRect) { .origin = { .x = _frame.origin.x + layoutElement.fb_layout.frame.origin.x, .y = _frame.origin.y + layoutElement.fb_layout.frame.origin.y, }, .size = { .width = layoutElement.fb_layout.frame.size.width, .height = layoutElement.fb_layout.frame.size.height, }, }; [layoutElement fb_applyLayoutToViewHierachy]; } } @end ================================================ FILE: FlexBoxLayout/Classes/Component/UIScrollView+FBLayout.h ================================================ // // UIScrollView+FBLayout.h // Pods // // Created by 沈强 on 2017/1/20. // // #import #import "FBLayoutDiv.h" @interface UIScrollView (FBLayout) /** ScrollView layout div make contentSize auto size */ @property(nonatomic, strong) FBLayoutDiv *fb_contentDiv; /** remove layout */ - (void)fb_clearLayout; @end ================================================ FILE: FlexBoxLayout/Classes/Component/UIScrollView+FBLayout.m ================================================ // // UIScrollView+FBLayout.m // Pods // // Created by 沈强 on 2017/1/20. // // #import "UIScrollView+FBLayout.h" #import @implementation UIScrollView (FBLayout) + (void)load { SEL originalSelector = @selector(layoutSubviews); SEL swizzledSelector = NSSelectorFromString([@"fb_" stringByAppendingString:NSStringFromSelector(originalSelector)]); Method originalMethod = class_getInstanceMethod(self, originalSelector); Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector); method_exchangeImplementations(originalMethod, swizzledMethod); } - (FBLayoutDiv *)fb_contentDiv { return objc_getAssociatedObject(self, _cmd); } - (void)setFb_contentDiv:(FBLayoutDiv *)fb_contentDiv { FBLayoutDiv *contentDiv = [self fb_contentDiv]; if (contentDiv != fb_contentDiv) { objc_setAssociatedObject(self, @selector(fb_contentDiv), fb_contentDiv, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } } - (void)fb_clearLayout { [self setFb_contentDiv:nil]; } - (void)fb_layoutSubviews { [self fb_layoutSubviews]; FBLayoutDiv *contentDiv = [self fb_contentDiv]; if (contentDiv) { self.contentSize = (CGSize){ .width = contentDiv.frame.size.width > self.frame.size.width ? contentDiv.frame.size.width : self.frame.size.width, .height = contentDiv.frame.size.height > self.frame.size.height ? contentDiv.frame.size.height: self.frame.size.height, }; } } @end ================================================ FILE: FlexBoxLayout/Classes/Component/UITableView+FBLayout.h ================================================ // // UITableView+fbLayout.h // Pods // // Created by 沈强 on 2017/1/11. // // #import NS_ASSUME_NONNULL_BEGIN typedef UIView *_Nonnull (^FBCellBlock)(NSIndexPath *indexPath); @interface UITableView (FBLayout) /** setting the cell contentView Size, defalut width of UITableView */ @property(nonatomic) CGFloat fb_constrainedWidth; /** cache layout */ @property(nonatomic) BOOL fb_cacheLayout; /** cache content view cannot be together with fb_CacheLayout at the same time */ @property(nonatomic) BOOL fb_cacheContentView; /** get the height of cell @param indexPath @return */ - (CGFloat)fb_heightForIndexPath:(NSIndexPath *)indexPath; /** get the cell of indexPath @param indexPath @return */ - (UITableViewCell *)fb_cellForIndexPath:(NSIndexPath *)indexPath; /** set the cell content view @param cellBlock */ - (void)fb_setCellContnetViewBlockForIndexPath:(FBCellBlock)cellBlock; /** content view @param indexPath indexPath @return nil if cell is not visible or index path is out of range */ - (UIView *)fb_contentViewForIndexPath:(NSIndexPath *)indexPath; /** remove all cache */ - (void)fb_removeAllCache; @end NS_ASSUME_NONNULL_END ================================================ FILE: FlexBoxLayout/Classes/Component/UITableView+FBLayout.m ================================================ // // UITableView+fbLayout.m // Pods // // Created by 沈强 on 2017/1/11. // // #import "UITableView+FBLayout.h" #import #import "UIView+CellStyle.h" #import "UIView+FBLayout.h" static NSString *kCellIdentifier = @"fb_kCellIdentifier"; #define CACHE_CONTENT_VIEW objc_getAssociatedObject(self, @selector(fb_cacheContentView:)) #define CACHE_LAYOUT objc_getAssociatedObject(self, @"fb_cacheLayout") static NSInteger contentViewTag = 6868; @implementation UITableView (FBLayout) + (void)load { SEL interceptedSelectors[] = { @selector(reloadData), @selector(insertSections:withRowAnimation:), @selector(deleteSections:withRowAnimation:), @selector(reloadSections:withRowAnimation:), @selector(moveSection:toSection:), @selector(insertRowsAtIndexPaths:withRowAnimation:), @selector(deleteRowsAtIndexPaths:withRowAnimation:), @selector(reloadRowsAtIndexPaths:withRowAnimation:), @selector(moveRowAtIndexPath:toIndexPath:) }; for (NSUInteger index = 0; index < sizeof(interceptedSelectors) / sizeof(SEL); ++index) { SEL originalSelector = interceptedSelectors[index]; SEL swizzledSelector = NSSelectorFromString([@"fb_" stringByAppendingString:NSStringFromSelector(originalSelector)]); Method originalMethod = class_getInstanceMethod(self, originalSelector); Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector); method_exchangeImplementations(originalMethod, swizzledMethod); } } - (void)setFb_constrainedWidth:(CGFloat)fb_constrainedWidth { objc_setAssociatedObject(self, _cmd, @(fb_constrainedWidth), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (CGFloat)fb_constrainedWidth { return [objc_getAssociatedObject(self, @selector(setFb_constrainedWidth:)) doubleValue];; } - (void)setFb_cacheLayout:(BOOL)fb_cacheLayout { if (fb_cacheLayout) { self.fb_cacheContentView = NO; } else { NSMutableArray *cacheLayout = CACHE_LAYOUT; [cacheLayout removeAllObjects]; } objc_setAssociatedObject(self, _cmd, @(fb_cacheLayout), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (BOOL)fb_cacheLayout { return [objc_getAssociatedObject(self, @selector(setFb_cacheLayout:)) boolValue];; } - (void)setFb_cacheContentView:(BOOL)fb_cacheContentView { if (fb_cacheContentView) { self.fb_cacheLayout = NO; } else { NSMutableArray *cacheContentViews = CACHE_CONTENT_VIEW; [cacheContentViews removeAllObjects]; } objc_setAssociatedObject(self, _cmd, @(fb_cacheContentView), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (BOOL)fb_cacheContentView { return objc_getAssociatedObject(self, @selector(setFb_cacheContentView:)) ? [ objc_getAssociatedObject(self, @selector(setFb_cacheContentView:)) boolValue] :YES; } - (CGFloat)fb_heightForIndexPath:(NSIndexPath *)indexPath { NSMutableArray *cacheLayout = CACHE_LAYOUT; FBViewLayoutCache *viewLayoutCache = nil; if (self.fb_cacheLayout) { if (cacheLayout.count > indexPath.section) { NSArray* sectionCacheViews = cacheLayout[indexPath.section]; if (sectionCacheViews.count > indexPath.row) { viewLayoutCache = sectionCacheViews[indexPath.row]; } } if (viewLayoutCache) { return viewLayoutCache.frame.size.height; } } return [self fb_cacheContentView:indexPath].frame.size.height; } - (UITableViewCell *)fb_cellForIndexPath:(NSIndexPath *)indexPath { return [self fb_cacheCellForIndexPath:indexPath]; } - (UIView *)fb_contentViewForIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath]; return [cell.contentView viewWithTag:contentViewTag]; } - (void)fb_setCellContnetViewBlockForIndexPath:(FBCellBlock)cellBlock { static dispatch_once_t token; dispatch_once(&token, ^{ [self registerClass:[UITableViewCell class] forCellReuseIdentifier:kCellIdentifier]; }); objc_setAssociatedObject(self, _cmd, cellBlock, OBJC_ASSOCIATION_COPY_NONATOMIC); } #pragma mark - caches - (UITableViewCell *)fb_cacheCellForIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [self dequeueReusableCellWithIdentifier:kCellIdentifier forIndexPath:indexPath]; UIView *cellContentView = [self fb_cacheContentView:indexPath]; cell.fb_drawsAsynchronously = YES; cellContentView.fb_drawsAsynchronously = YES; cell.selectionStyle = cellContentView.fb_selectionStyle; cell.backgroundColor = cellContentView.backgroundColor; cell.clipsToBounds = cellContentView.clipsToBounds; [self fb_configContentView:cellContentView forCell:cell]; return cell; } - (UIView *)fb_cacheContentView:(NSIndexPath *)indexPath { NSMutableArray *cacheContentViews = CACHE_CONTENT_VIEW; NSMutableArray *cacheLayout = CACHE_LAYOUT; if (!cacheContentViews) { cacheContentViews = [NSMutableArray array]; objc_setAssociatedObject(self, _cmd, cacheContentViews, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fb_removeAllCache) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; } if (!cacheLayout) { cacheLayout = [NSMutableArray array]; objc_setAssociatedObject(self, @"fb_cacheLayout", cacheLayout, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } UIView * cellContentView = nil; NSMutableArray* sectionContentViews = nil; if (self.fb_cacheContentView) { if (cacheContentViews.count > indexPath.section) { sectionContentViews = cacheContentViews[indexPath.section]; if (sectionContentViews.count > indexPath.row) { cellContentView = sectionContentViews[indexPath.row]; } } else { NSAssert(cacheContentViews.count == indexPath.section, @"%@ section is error",@(indexPath.section)); cacheContentViews[indexPath.section] = [NSMutableArray array]; } } if (!cellContentView || [cellContentView isEqual:[NSNull null]]) { FBCellBlock cellBlock = objc_getAssociatedObject(self, @selector(fb_setCellContnetViewBlockForIndexPath:)); if (cellBlock) { cellContentView = cellBlock(indexPath); FBViewLayoutCache *viewLayoutCache = nil; if (self.fb_cacheLayout) { if (cacheLayout.count > indexPath.section) { NSArray* sectionCacheViews = cacheLayout[indexPath.section]; if (sectionCacheViews.count > indexPath.row) { viewLayoutCache = sectionCacheViews[indexPath.row]; } } else { NSAssert(cacheLayout.count == indexPath.section, @"%@ section is error",@(indexPath.section)); cacheLayout[indexPath.section] = [NSMutableArray array]; } } if (viewLayoutCache) { [cellContentView.fb_layout applyLayoutCache:viewLayoutCache]; } else { [cellContentView fb_applyLayouWithSize:CGSizeMake(self.fb_constrainedWidth?:self.frame.size.width, fb_undefined)]; if (self.fb_cacheLayout) { [cacheLayout[indexPath.section] insertObject:[cellContentView.fb_layout layoutCache] atIndex:indexPath.row]; } } } else { cellContentView = [UIView new]; } if (self.fb_cacheContentView) { [cacheContentViews[indexPath.section] insertObject:cellContentView atIndex:indexPath.row]; } } cellContentView.tag = contentViewTag; return cellContentView; } - (void)fb_removeAllCache { [self fb_removeAllCacheContentViews]; } - (void)fb_removeAllCacheContentViews { [CACHE_CONTENT_VIEW removeAllObjects]; [CACHE_LAYOUT removeAllObjects]; } - (void)fb_removeCacheContentViewsAtSection:(NSUInteger)section { if (self.fb_cacheContentView) { [CACHE_CONTENT_VIEW removeObjectAtIndex:section]; } else if (self.fb_cacheLayout) { [CACHE_LAYOUT removeObjectAtIndex:section]; } } - (void)fb_removeCacheContentViewAtIndexPath:(NSIndexPath *)indexPath { if (self.fb_cacheContentView) { [CACHE_CONTENT_VIEW[indexPath.section] removeObjectAtIndex:indexPath.row]; } else if(self.fb_cacheLayout) { [CACHE_LAYOUT[indexPath.section] removeObjectAtIndex:indexPath.row]; } } - (void)fb_addCacheContentViewsAtSection:(NSUInteger)section { if (self.fb_cacheContentView) { [CACHE_CONTENT_VIEW insertObject:[NSMutableArray array] atIndex:section]; } else if(self.fb_cacheLayout) { [CACHE_LAYOUT insertObject:[NSMutableArray array] atIndex:section]; } } - (void)fb_addCacheContentViewsAtIndexPath:(NSIndexPath *)indexPath { if (self.fb_cacheContentView) { [CACHE_CONTENT_VIEW[indexPath.section] insertObject:[NSNull null] atIndex:indexPath.row]; } else if(self.fb_cacheLayout) { [CACHE_LAYOUT[indexPath.section] insertObject:[NSNull null] atIndex:indexPath.row]; } } - (void)fb_reloadCacheContentViewsAtSection:(NSUInteger)section { if (self.fb_cacheContentView) { [CACHE_CONTENT_VIEW[section] removeAllObjects]; } else if (self.fb_cacheLayout) { [CACHE_LAYOUT[section] removeAllObjects]; } } - (void)fb_reloadCacheContentViewsAtIndexPath:(NSIndexPath *)indexPath { if (self.fb_cacheContentView) { [CACHE_CONTENT_VIEW[indexPath.section] replaceObjectAtIndex:indexPath.row withObject:[NSNull null]]; } else if (self.fb_cacheLayout) { [CACHE_LAYOUT[indexPath.section] replaceObjectAtIndex:indexPath.row withObject:[NSNull null]]; } } - (void)fb_moveCacheContentViewsSection:(NSInteger)section toSection:(NSInteger)newSection { if (self.fb_cacheContentView) { [CACHE_CONTENT_VIEW exchangeObjectAtIndex:section withObjectAtIndex:newSection]; } else if(self.fb_cacheLayout) { [CACHE_LAYOUT exchangeObjectAtIndex:section withObjectAtIndex:newSection]; } } - (void)fb_moveCacheContentViewsAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath { if (self.fb_cacheContentView) { UIView *view1 = CACHE_CONTENT_VIEW[indexPath.section][indexPath.row]; UIView *view2 = CACHE_CONTENT_VIEW[newIndexPath.section][newIndexPath.row]; CACHE_CONTENT_VIEW[indexPath.section][indexPath.row] = view2; CACHE_CONTENT_VIEW[newIndexPath.section][newIndexPath.row] = view1; } else if (self.fb_cacheLayout) { UIView *view1 = CACHE_LAYOUT[indexPath.section][indexPath.row]; UIView *view2 = CACHE_LAYOUT[newIndexPath.section][newIndexPath.row]; CACHE_LAYOUT[indexPath.section][indexPath.row] = view2; CACHE_LAYOUT[newIndexPath.section][newIndexPath.row] = view1; } } - (void)fb_configContentView:(UIView *)contentView forCell:(UITableViewCell *)cell{ UIView *removedView = [cell.contentView viewWithTag:contentViewTag]; [removedView removeFromSuperview]; [cell.contentView addSubview:contentView]; } #pragma mark - interceptedSelectors - (void)fb_reloadData { [self fb_removeAllCacheContentViews]; [self fb_reloadData]; } - (void)fb_insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation{ [sections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { [self fb_addCacheContentViewsAtSection:idx]; }]; [self fb_insertSections:sections withRowAnimation:animation]; } - (void)fb_deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation { [sections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { [self fb_removeCacheContentViewsAtSection:idx]; }]; [self fb_deleteSections:sections withRowAnimation:animation]; } - (void)fb_reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation { [sections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { [self fb_reloadCacheContentViewsAtSection:idx]; }]; [self fb_reloadSections:sections withRowAnimation:animation]; } - (void)fb_moveSection:(NSInteger)section toSection:(NSInteger)newSection { [self fb_moveCacheContentViewsSection:section toSection:newSection]; [self fb_moveSection:section toSection:newSection]; } - (void)fb_insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation { [indexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { [self fb_addCacheContentViewsAtIndexPath:obj]; }]; [self fb_insertRowsAtIndexPaths:indexPaths withRowAnimation:animation]; } - (void)fb_deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation { [indexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { [self fb_removeCacheContentViewAtIndexPath:obj]; }]; [self fb_deleteRowsAtIndexPaths:indexPaths withRowAnimation:animation]; } - (void)fb_reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation { [indexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { [self fb_reloadCacheContentViewsAtIndexPath:obj]; }]; [self fb_reloadRowsAtIndexPaths:indexPaths withRowAnimation:animation]; } - (void)fb_moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath { [self fb_moveCacheContentViewsAtIndexPath:indexPath toIndexPath:newIndexPath]; [self fb_moveRowAtIndexPath:indexPath toIndexPath:newIndexPath]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } @end ================================================ FILE: FlexBoxLayout/Classes/Component/UIView+CellStyle.h ================================================ // // UIView+CellStyle.h // Pods // // Created by 沈强 on 2017/1/12. // // #import @interface UIView (CellStyle) /** set cell selectionStyle if view add to the cell. */ @property(nonatomic) UITableViewCellSelectionStyle fb_selectionStyle; @end ================================================ FILE: FlexBoxLayout/Classes/Component/UIView+CellStyle.m ================================================ // // UIView+CellStyle.m // Pods // // Created by 沈强 on 2017/1/12. // // #import "UIView+CellStyle.h" #import @implementation UIView (CellStyle) - (void)setFb_selectionStyle:(UITableViewCellSelectionStyle)fb_selectionStyle { objc_setAssociatedObject(self, _cmd, @(fb_selectionStyle), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UITableViewCellSelectionStyle)fb_selectionStyle { return [objc_getAssociatedObject(self, @selector(setFb_selectionStyle:)) integerValue];; } @end ================================================ FILE: FlexBoxLayout/Classes/Component/UIView+FBLayout.h ================================================ // // UIView+CSJSLayout.h // CSJSView // // Created by 沈强 on 16/8/31. // Copyright © 2016年 沈强. All rights reserved. // #import #import "FBLayout.h" #import "FBLayoutProtocol.h" @interface UIView (FBLayout) @property(nonatomic) BOOL fb_drawsAsynchronously; /** fit view size to content size */ - (void)fb_wrapContent; /** set view layout properties @param direction @param justifyContent @param alignItems @param children */ - (void)fb_setFlexDirection:(FBFlexDirection)direction justifyContent:(FBJustify)justifyContent alignItems:(FBAlign)alignItems children:(NSArray>*)children; @end ================================================ FILE: FlexBoxLayout/Classes/Component/UIView+FBLayout.m ================================================ // // UIView+CSJSLayout.m // CSJSView // // Created by 沈强 on 16/8/31. // Copyright © 2016年 沈强. All rights reserved. // #import "UIView+FBLayout.h" #import #import "FBAsyLayoutTransaction.h" extern void YGSetMesure(FBLayout *layout); const CGSize fb_undefinedSize = { .width = YGUndefined, .height = YGUndefined, }; const CGFloat fb_undefined = YGUndefined; @implementation UIView (FBLayout) - (void)setFbStyles:(NSDictionary *)fbStyles { [self fb_layout].fbStyles = fbStyles; } - (NSDictionary *)fbStyles { return [self fb_layout].fbStyles; } - (void)setFb_children:(NSArray> *)children { if ([self fb_children] == children) { return; } objc_setAssociatedObject(self, @selector(fb_children), children, OBJC_ASSOCIATION_COPY_NONATOMIC); [[self fb_layout] removeAllChildren]; for (id layoutElement in children) { NSAssert([layoutElement conformsToProtocol:NSProtocolFromString(@"FBLayoutProtocol")], @"child %@ has no conformsToProtocol FBLayoutProtocol", self); [[self fb_layout] addChild:layoutElement.fb_layout]; } } - (void)fb_addChild:(id)layout { NSAssert([layout conformsToProtocol:NSProtocolFromString(@"FBLayoutProtocol")], @"child %@ has no conformsToProtocol FBLayoutProtocol", self); NSMutableArray *newChildren = [[self fb_children] mutableCopy]; [newChildren addObject:layout]; self.fb_children = newChildren; } - (void)fb_addChildren:(NSArray> *)children { NSMutableArray *newChildren = [[self fb_children] mutableCopy]; [newChildren addObjectsFromArray:children]; self.fb_children = newChildren; } - (void)fb_insertChild:(id)layout atIndex:(NSInteger)index { NSAssert([layout conformsToProtocol:NSProtocolFromString(@"FBLayoutProtocol")], @"child %@ has no conformsToProtocol FBLayoutProtocol", self); NSMutableArray *newChildren = [[self fb_children] mutableCopy]; [newChildren insertObject:layout atIndex:index]; self.fb_children = newChildren; } - (id)fb_childLayoutAtIndex:(NSUInteger)index { return [self.fb_children objectAtIndex:index]; } - (void)fb_removeChild:(id)layout { NSMutableArray *newChildren = [[self fb_children] mutableCopy]; [newChildren removeObject:layout]; self.fb_children = newChildren; } - (void)fb_removeAllChildren { self.fb_children = nil; } - (NSArray *)fb_children { return objc_getAssociatedObject(self, _cmd) ?:[NSMutableArray array]; } - (void)fb_setFlexDirection:(FBFlexDirection)direction justifyContent:(FBJustify)justifyContent alignItems:(FBAlign)alignItems children:(NSArray>*)children { [self fb_makeLayout:^(FBLayout *layout) { [layout setFlexDirection:direction]; [layout setJustifyContent:justifyContent]; [layout setAlignItems:alignItems]; }]; [self setFb_children:children]; } - (void)fb_wrapContent { [self fb_layout].mesureSize = [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)]; YGSetMesure([self fb_layout]); } - (void)setFb_drawsAsynchronously:(BOOL)fb_drawsAsynchronously { self.layer.drawsAsynchronously = fb_drawsAsynchronously; } - (BOOL)fb_drawsAsynchronously { return self.layer.drawsAsynchronously; } - (FBLayout *)fb_layout { FBLayout *layout = objc_getAssociatedObject(self, _cmd); if (!layout) { layout = [FBLayout new]; layout.context = self; objc_setAssociatedObject(self, _cmd, layout, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return layout; } #pragma mark - layout - (void)fb_applyLayouWithSize:(CGSize)size { [[self fb_layout] calculateLayoutWithSize:size]; self.frame = [self fb_layout].frame; [self fb_applyLayoutToViewHierachy]; } - (void)fb_asyApplyLayoutWithSize:(CGSize)size { [FBAsyLayoutTransaction addCalculateTransaction:^{ [[self fb_layout] calculateLayoutWithSize:size]; } complete:^{ self.frame = [self fb_layout].frame; [self fb_applyLayoutToViewHierachy]; }]; } - (void)fb_applyLayoutToViewHierachy { for (id layoutElement in [self fb_children]) { layoutElement.frame = layoutElement.fb_layout.frame; [layoutElement fb_applyLayoutToViewHierachy]; } } - (FBLayout *)fb_makeLayout:(void(^)(FBLayout *layout))layout { if (layout) { layout([self fb_layout]); } return [self fb_layout]; } @end ================================================ FILE: FlexBoxLayout/Classes/FlexBoxLayout.h ================================================ // // FlexBoxLayout.h // Pods // // Created by 沈强 on 2017/2/9. // // #ifndef FlexBoxLayout_h #define FlexBoxLayout_h #import "FBLayout.h" #import "FBLayoutDiv.h" #import "FBLayoutProtocol.h" #import "UIScrollView+FBLayout.h" #import "UIView+CellStyle.h" #import "UITableView+FBLayout.h" #import "UIView+FBLayout.h" #endif /* FlexBoxLayout_h */ ================================================ FILE: FlexBoxLayout/Classes/Layout/FBLayout+Private.h ================================================ // // FBLayout+Private.h // Pods // // Created by 沈强 on 2017/2/9. // // #import "FBLayout.h" #import "Yoga.h" #import "FBViewLayoutCache.h" @interface FBLayout (Private) @property(nonatomic, weak) id context; @property(nonatomic, weak) FBLayout *parent; @property(nonatomic, copy)NSDictionary *fbStyles; @property(nonatomic, readonly, assign) YGNodeRef fbNode; @property(nonatomic, readonly, assign) CGRect frame; @property(nonatomic, assign) CGSize mesureSize; - (FBViewLayoutCache *)layoutCache; - (void)applyLayoutCache:(FBViewLayoutCache *)layoutCache; - (NSArray *)allChildren; - (void)addChild:(FBLayout *)layout; - (void)addChildren:(NSArray *)children; - (void)insertChild:(FBLayout *)layout atIndex:(NSInteger)index; - (FBLayout *)childLayoutAtIndex:(NSUInteger)index; - (void)removeChild:(FBLayout *)layout; - (void)removeAllChildren; - (void)calculateLayoutWithSize:(CGSize)size; - (void)setDirection:(FBDirection)direction; - (void)setFlexDirection:(FBFlexDirection)flexDirection; - (void)setJustifyContent:(FBJustify)justifyContent; - (void)setAlignContent:(FBAlign)alignContent; - (void)setAlignItems:(FBAlign)alignItems; - (void)setAlignSelf:(FBAlign)alignSelf; - (void)setPositionType:(FBPositionType)positionType; - (void)setFlexWrap:(FBWrap)flexWrap; - (void)setFlexGrow:(CGFloat)flexGrow; - (void)setFlexShrink:(CGFloat)flexShrink; - (void)setFlexBasis:(CGFloat)flexBasis; - (void)setPosition:(CGFloat)position forEdge:(FBEdge)edge; - (void)setMargin:(CGFloat)margin forEdge:(FBEdge)edge; - (void)setPadding:(CGFloat)padding forEdge:(FBEdge)edge; - (void)setWidth:(CGFloat)width; - (void)setHeight:(CGFloat)height; - (void)setSize:(CGSize)size; - (void)setMinWidth:(CGFloat)minWidth; - (void)setMinHeight:(CGFloat)minHeight; - (void)setMinSize:(CGSize)minSize; - (void)setMaxWidth:(CGFloat)maxWidth; - (void)setMaxHeight:(CGFloat)maxHeight; - (void)setMaxSize:(CGSize)maxSize; - (void)setAspectRatio:(CGFloat)aspectRatio; @end ================================================ FILE: FlexBoxLayout/Classes/Layout/FBLayout.h ================================================ // // FBLayout.h // // Created by 沈强 on 16/8/28. // Copyright © 2016年 沈强. All rights reserved. // #import typedef enum FBFlexDirection { FBFlexDirectionColumn, FBFlexDirectionColumnReverse, FBFlexDirectionRow, FBFlexDirectionRowReverse, } FBFlexDirection; typedef enum FBMeasureMode { FBMeasureModeUndefined, FBMeasureModeExactly, FBMeasureModeAtMost, } FBMeasureMode; typedef enum FBPrintOptions { FBPrintOptionsLayout = 1, FBPrintOptionsStyle = 2, FBPrintOptionsChildren = 4, } FBPrintOptions; typedef enum FBEdge { FBEdgeLeft, FBEdgeTop, FBEdgeRight, FBEdgeBottom, FBEdgeStart, FBEdgeEnd, FBEdgeHorizontal, FBEdgeVertical, FBEdgeAll, } FBEdge; typedef enum FBPositionType { FBPositionTypeRelative, FBPositionTypeAbsolute, } FBPositionType; typedef enum FBDimension { FBDimensionWidth, FBDimensionHeight, } FBDimension; typedef enum FBJustify { FBJustifyFlexStart, FBJustifyCenter, FBJustifyFlexEnd, FBJustifySpaceBetween, FBJustifySpaceAround, } FBJustify; typedef enum FBDirection { FBDirectionInherit, FBDirectionLTR, FBDirectionRTL, } FBDirection; typedef enum FBLogLevel { FBLogLevelError, FBLogLevelWarn, FBLogLevelInfo, FBLogLevelDebug, FBLogLevelVerbose, } FBLogLevel; typedef enum FBWrap { FBWrapNoWrap, FBWrapWrap, FBWrapCount, } FBWrap; typedef enum FBAlign { FBAlignAuto, FBAlignFlexStart, FBAlignCenter, FBAlignFlexEnd, FBAlignStretch, } FBAlign; NS_ASSUME_NONNULL_BEGIN @interface FBLayout : NSObject - (FBLayout *)flexDirection; - (FBLayout *)justifyContent; - (FBLayout *)alignContent; - (FBLayout *)alignItems; - (FBLayout *)alignSelf; - (FBLayout *)positionType; - (FBLayout *)flexWrap; - (FBLayout *)flexGrow; - (FBLayout *)flexShrink; - (FBLayout *)flexBasiss; - (FBLayout *)position; - (FBLayout *)margin; - (FBLayout *)padding; - (FBLayout *)width; - (FBLayout *)height; - (FBLayout *)minWidth; - (FBLayout *)minHeight; - (FBLayout *)maxWidth; - (FBLayout *)maxHeight; - (FBLayout *)size; - (FBLayout *)maxSize; - (FBLayout *)minSize; - (FBLayout *)aspectRatio; - (FBLayout * (^)(id attr))equalTo; - (FBLayout * (^)(CGSize attr))equalToSize; - (FBLayout * (^)(UIEdgeInsets attr))equalToEdgeInsets; - (FBLayout * (^)())wrapContent; - (FBLayout * (^)(NSArray*))children; @end NS_ASSUME_NONNULL_END ================================================ FILE: FlexBoxLayout/Classes/Layout/FBLayout.m ================================================ // // FBLayout.m // // Created by 沈强 on 16/8/28. // Copyright © 2016年 沈强. All rights reserved. // #import "FBLayout.h" #import "FBLayout+Private.h" #import "FBLayoutProtocol.h" #import "Yoga.h" #import "FBLayoutDiv.h" static CGFloat FBRoundPixelValue(CGFloat value) { static CGFloat scale; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^(){ scale = [UIScreen mainScreen].scale; }); return round(value * scale) / scale; } 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 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); __block CGSize sizeThatFits; if ([[NSThread currentThread] isMainThread]) { sizeThatFits = [view sizeThatFits:(CGSize) { .width = constrainedWidth, .height = constrainedHeight, }]; } else { dispatch_sync(dispatch_get_main_queue(), ^{ sizeThatFits = [view sizeThatFits:(CGSize) { .width = constrainedWidth, .height = constrainedHeight, }]; }); } return (YGSize) { .width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode), .height = YGSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode), }; } void YGSetMesure(FBLayout *layout) { if ([layout.context isKindOfClass:[UIView class]] && layout.allChildren.count == 0) { YGNodeSetMeasureFunc(layout.fbNode, YGMeasureView); } else { YGNodeSetMeasureFunc(layout.fbNode, NULL); } } @interface FBLayout() { NSMutableArray *_children; } @property(nonatomic, strong) NSMutableArray *styleNames; @property(nonatomic, weak) id context; @property(nonatomic, weak) FBLayout *parent; @property(nonatomic, copy)NSDictionary *fbStyles; @property(nonatomic, readonly, assign) YGNodeRef fbNode; @property(nonatomic, readonly, assign) CGRect frame; @property(nonatomic, assign) CGSize mesureSize; @end @implementation FBLayout - (instancetype)init { if (self = [super init]) { _fbNode = YGNodeNew(); _children = [NSMutableArray array]; _styleNames = [NSMutableArray array]; } return self; } - (void)setContext:(id)context { _context = context; YGNodeSetContext(_fbNode, (__bridge void *)(context)); } - (void)dealloc { YGNodeFree(_fbNode); } - (CGRect)frame { return CGRectMake(FBRoundPixelValue(YGNodeLayoutGetLeft(_fbNode)), FBRoundPixelValue(YGNodeLayoutGetTop(_fbNode)), FBRoundPixelValue(YGNodeLayoutGetWidth(_fbNode)), FBRoundPixelValue(YGNodeLayoutGetHeight(_fbNode))); } - (FBViewLayoutCache *)layoutCache { FBViewLayoutCache *layoutCache = [FBViewLayoutCache new]; layoutCache.frame = ((id)self.context).frame; NSMutableArray *childrenLayoutCache = [NSMutableArray arrayWithCapacity:self.allChildren.count]; for (FBLayout *childLayout in self.allChildren) { [childrenLayoutCache addObject:[childLayout layoutCache]]; } layoutCache.childrenCache = [childrenLayoutCache copy]; return layoutCache; } - (void)applyLayoutCache:(FBViewLayoutCache *)layoutCache { id view = self.context; view.frame = layoutCache.frame; if (view.fb_children.count != layoutCache.childrenCache.count) { return; } for (int i = 0; i < layoutCache.childrenCache.count; i++) { FBViewLayoutCache* childLayoutCache = layoutCache.childrenCache[i]; id childView = view.fb_children[i]; [childView.fb_layout applyLayoutCache:childLayoutCache]; } } #pragma mark - children - (NSArray *)allChildren { return [_children copy]; } - (FBLayout *)childLayoutAtIndex:(NSUInteger)index { return [_children objectAtIndex:index]; } - (void)addChild:(FBLayout *)layout { [_children addObject:layout]; layout.parent = self; YGNodeInsertChild(_fbNode, layout.fbNode, YGNodeGetChildCount(_fbNode)); } - (void)addChildren:(NSArray *)children { for (FBLayout *layout in children) { [self addChild:layout]; } } - (void)insertChild:(FBLayout *)layout atIndex:(NSInteger)index { [_children insertObject:layout atIndex:index]; layout.parent = self; YGNodeInsertChild(_fbNode, layout.fbNode, (uint32_t)index); } - (void)removeChild:(FBLayout *)layout { [_children removeObject:layout]; YGNodeRemoveChild(_fbNode, layout.fbNode); } - (void)removeAllChildren { [_children removeAllObjects]; if (_fbNode == NULL) { return; } while (YGNodeGetChildCount(_fbNode) > 0) { YGNodeRemoveChild(_fbNode, YGNodeGetChild(_fbNode, YGNodeGetChildCount(_fbNode) - 1)); } } #pragma mark - calculate - (void)calculateLayoutWithSize:(CGSize)size { YGNodeCalculateLayout(_fbNode, size.width, size.height, YGNodeStyleGetDirection(_fbNode)); } #pragma mark - FB styles #define FB_STYLE_FILL(key)\ do {\ id value = _fbStyles[@"FB"#key"AttributeName"];\ if (value) {\ [self set##key:[(NSNumber *)value floatValue]];\ }\ } while(0); #define FB_STYLE_FILL_ALL_DIRECTION(key) \ do {\ id value = _fbStyles[@"FB"#key"AttributeName"];\ if (value) {\ [self set##key:[(NSValue *)value UIEdgeInsetsValue].left forEdge:FBEdgeLeft];\ [self set##key:[(NSValue *)value UIEdgeInsetsValue].top forEdge:FBEdgeTop];\ [self set##key:[(NSValue *)value UIEdgeInsetsValue].right forEdge:FBEdgeRight];\ [self set##key:[(NSValue *)value UIEdgeInsetsValue].bottom forEdge:FBEdgeBottom];\ }\ } while(0); #define FB_STYLE_FILL_ALL_SIZE(key) \ do {\ id value = _fbStyles[@"FB"#key"AttributeName"];\ if (value) {\ [self set##key:[(NSValue *)value CGSizeValue]];\ }\ } while(0); - (void)setFbStyles:(NSDictionary *)fbStyles { if (_fbStyles == fbStyles) { return; } _fbStyles = fbStyles; FB_STYLE_FILL(Direction) FB_STYLE_FILL(FlexDirection) FB_STYLE_FILL(JustifyContent) FB_STYLE_FILL(AlignContent) FB_STYLE_FILL(AlignItems) FB_STYLE_FILL(AlignSelf) FB_STYLE_FILL(PositionType) FB_STYLE_FILL(FlexWrap) FB_STYLE_FILL(FlexGrow) FB_STYLE_FILL(FlexShrink) FB_STYLE_FILL(FlexBasis) FB_STYLE_FILL_ALL_DIRECTION(Position) FB_STYLE_FILL_ALL_DIRECTION(Margin) FB_STYLE_FILL_ALL_DIRECTION(Padding) FB_STYLE_FILL(Width) FB_STYLE_FILL(Height) FB_STYLE_FILL(MinWidth) FB_STYLE_FILL(MinHeight) FB_STYLE_FILL(MaxWidth) FB_STYLE_FILL(MaxHeight) FB_STYLE_FILL(AspectRatio) FB_STYLE_FILL_ALL_SIZE(Size) FB_STYLE_FILL_ALL_SIZE(MinSize) FB_STYLE_FILL_ALL_SIZE(MaxSize) } - (void)setDirection:(FBDirection)direction { YGNodeStyleSetDirection(_fbNode, (YGDirection)direction); } - (void)setFlexDirection:(FBFlexDirection)flexDirection { YGNodeStyleSetFlexDirection(_fbNode, (YGFlexDirection)flexDirection); } - (void)setJustifyContent:(FBJustify)justifyContent { YGNodeStyleSetJustifyContent(_fbNode, (YGJustify)justifyContent); } - (void)setAlignContent:(FBAlign)alignContent { YGNodeStyleSetAlignContent(_fbNode, (YGAlign)alignContent); } - (void)setAlignItems:(FBAlign)alignItems { YGNodeStyleSetAlignItems(_fbNode, (YGAlign)alignItems); } - (void)setAlignSelf:(FBAlign)alignSelf { YGNodeStyleSetAlignSelf(_fbNode, (YGAlign)alignSelf); } - (void)setPositionType:(FBPositionType)positionType { YGNodeStyleSetPositionType(_fbNode, (YGPositionType)positionType); } - (void)setFlexWrap:(FBWrap)flexWrap { YGNodeStyleSetFlexWrap(_fbNode, (YGWrap)flexWrap); } - (void)setFlexGrow:(CGFloat)flexGrow { YGNodeStyleSetFlexGrow(_fbNode, flexGrow); } - (void)setFlexShrink:(CGFloat)flexShrink { YGNodeStyleSetFlexShrink(_fbNode, flexShrink); } - (void)setFlexBasis:(CGFloat)flexBasis { YGNodeStyleSetFlexBasis(_fbNode, flexBasis); } - (void)setPosition:(CGFloat)position forEdge:(FBEdge)edge { YGNodeStyleSetPosition(_fbNode, (YGEdge)edge, position); } - (void)setMargin:(CGFloat)margin forEdge:(FBEdge)edge { YGNodeStyleSetMargin(_fbNode, (YGEdge)edge, margin); } - (void)setPadding:(CGFloat)padding forEdge:(FBEdge)edge { YGNodeStyleSetPadding(_fbNode, (YGEdge)edge, padding); } - (void)setWidth:(CGFloat)width { YGNodeStyleSetWidth(_fbNode, width); } - (void)setHeight:(CGFloat)height { YGNodeStyleSetHeight(_fbNode, height); } - (void)setSize:(CGSize)size { YGNodeStyleSetWidth(_fbNode, size.width); YGNodeStyleSetHeight(_fbNode, size.height); } - (void)setMinWidth:(CGFloat)minWidth { YGNodeStyleSetMinWidth(_fbNode, minWidth); } - (void)setMinHeight:(CGFloat)minHeight { YGNodeStyleSetMinHeight(_fbNode, minHeight); } - (void)setMinSize:(CGSize)minSize { YGNodeStyleSetMinWidth(_fbNode, minSize.width); YGNodeStyleSetMinHeight(_fbNode, minSize.height); } - (void)setMaxWidth:(CGFloat)maxWidth { YGNodeStyleSetMaxWidth(_fbNode, maxWidth); } - (void)setMaxHeight:(CGFloat)maxHeight { YGNodeStyleSetMaxHeight(_fbNode, maxHeight); } - (void)setMaxSize:(CGSize)maxSize { YGNodeStyleSetMaxWidth(_fbNode, maxSize.width); YGNodeStyleSetMaxHeight(_fbNode, maxSize.height); } - (void)setAspectRatio:(CGFloat)aspectRatio { YGNodeStyleSetAspectRatio(_fbNode, aspectRatio); } #define CACHE_STYLES_NAME(name) [_styleNames addObject:@""#name]; \ return self; - (FBLayout *)flexDirection { CACHE_STYLES_NAME(FlexDirection) } - (FBLayout *)justifyContent { CACHE_STYLES_NAME(JustifyContent) } - (FBLayout *)alignContent { CACHE_STYLES_NAME(AlignContent) } - (FBLayout *)alignItems { CACHE_STYLES_NAME(AlignItems) } - (FBLayout *)alignSelf { CACHE_STYLES_NAME(AlignSelf) } - (FBLayout *)positionType { CACHE_STYLES_NAME(PositionType) } - (FBLayout *)flexWrap { CACHE_STYLES_NAME(FlexWrap) } - (FBLayout *)flexGrow { CACHE_STYLES_NAME(FlexGrow) } - (FBLayout *)flexShrink { CACHE_STYLES_NAME(FlexShrink) } - (FBLayout *)flexBasiss { CACHE_STYLES_NAME(FlexBasiss) } - (FBLayout *)position { CACHE_STYLES_NAME(Position) } - (FBLayout *)margin { CACHE_STYLES_NAME(Margin) } - (FBLayout *)padding { CACHE_STYLES_NAME(Padding) } - (FBLayout *)width { CACHE_STYLES_NAME(Width) } - (FBLayout *)height { CACHE_STYLES_NAME(Height) } - (FBLayout *)minWidth { CACHE_STYLES_NAME(MinWidth) } - (FBLayout *)minHeight { CACHE_STYLES_NAME(MinHeight) } - (FBLayout *)maxWidth { CACHE_STYLES_NAME(MaxWidth) } - (FBLayout *)maxHeight { CACHE_STYLES_NAME(MaxHeight) } - (FBLayout *)maxSize { CACHE_STYLES_NAME(MaxSize) } - (FBLayout *)minSize { CACHE_STYLES_NAME(MinSize) } - (FBLayout *)aspectRatio { CACHE_STYLES_NAME(AspectRatio) } - (FBLayout *)size { CACHE_STYLES_NAME(Size) } #define FB_STYLE(key, value)\ do {\ if ([_styleNames containsObject:@""#key]) {\ [self set##key:[(NSNumber *)value floatValue]];\ }\ } while(0); #define FB_STYLE_ALL_DIRECTION(key, value) \ do {\ if ([_styleNames containsObject:@""#key]) {\ [self set##key:value.left forEdge:FBEdgeLeft];\ [self set##key:value.top forEdge:FBEdgeTop];\ [self set##key:value.right forEdge:FBEdgeRight];\ [self set##key:value.bottom forEdge:FBEdgeBottom];\ }\ } while(0); #define FB_STYLE_ALL_SIZE(key, value) \ do {\ if ([_styleNames containsObject:@""#key]) {\ [self set##key:value];\ }\ } while(0); - (FBLayout * (^)(id attr))equalTo { return ^FBLayout* (id attr) { if ([attr conformsToProtocol:NSProtocolFromString(@"FBLayoutProtocol")]) { YGNodeCopyStyle(self.fbNode, [(id)attr fb_layout].fbNode); return self; } FB_STYLE(Direction,attr) FB_STYLE(FlexDirection,attr) FB_STYLE(JustifyContent,attr) FB_STYLE(AlignContent,attr) FB_STYLE(AlignItems,attr) FB_STYLE(AlignSelf,attr) FB_STYLE(PositionType,attr) FB_STYLE(FlexWrap,attr) FB_STYLE(FlexGrow,attr) FB_STYLE(FlexShrink,attr) FB_STYLE(FlexBasis,attr) FB_STYLE(Width,attr) FB_STYLE(Height,attr) FB_STYLE(MinWidth,attr) FB_STYLE(MinHeight,attr) FB_STYLE(MaxWidth,attr) FB_STYLE(MaxHeight,attr) FB_STYLE(AspectRatio,attr) [self.styleNames removeAllObjects]; return self; }; } - (FBLayout * (^)(CGSize attr))equalToSize { return ^FBLayout* (CGSize attr) { FB_STYLE_ALL_SIZE(Size,attr) FB_STYLE_ALL_SIZE(MinSize,attr) FB_STYLE_ALL_SIZE(MaxSize,attr) [self.styleNames removeAllObjects]; return self; }; } - (FBLayout * (^)(UIEdgeInsets attr))equalToEdgeInsets { return ^FBLayout* (UIEdgeInsets attr) { FB_STYLE_ALL_DIRECTION(Position,attr) FB_STYLE_ALL_DIRECTION(Margin,attr) FB_STYLE_ALL_DIRECTION(Padding,attr) [self.styleNames removeAllObjects]; return self; }; } - (FBLayout * (^)())wrapContent { return ^FBLayout* () { YGSetMesure(self); return self; }; } - (FBLayout * (^)(NSArray* children))children { return ^FBLayout* (NSArray* children) { [((id)self.context) fb_addChildren:children]; return self; }; } @end ================================================ FILE: FlexBoxLayout/Classes/Layout/FBLayoutProtocol.h ================================================ // // FBLayoutProtocol.h // CSJSView // // Created by 沈强 on 2016/12/23. // Copyright © 2016年 沈强. All rights reserved. // #import #import "FBLayout.h" #import "FBLayout+Private.h" extern const CGSize fb_undefinedSize; extern const CGFloat fb_undefined; @protocol FBLayoutProtocol @required @property(nonatomic, strong, readonly) FBLayout *fb_layout; /** the frame after calculates the layout */ @property(nonatomic, assign ) CGRect frame; /** children layout node */ @property(nonatomic, copy) NSArray> *fb_children; /** styles of layout */ @property(nonatomic, copy) NSDictionary *fbStyles; - (void)fb_addChild:(id)layout; - (void)fb_addChildren:(NSArray> *)children; - (void)fb_insertChild:(id)layout atIndex:(NSInteger)index; - (id)fb_childLayoutAtIndex:(NSUInteger)index; - (void)fb_removeChild:(id)layout; - (void)fb_removeAllChildren; - (void)fb_applyLayoutToViewHierachy; /** calculates the layout @param root layout size */ - (void)fb_applyLayouWithSize:(CGSize)size; /** calculates the layout asynchronously @param root layout size */ - (void)fb_asyApplyLayoutWithSize:(CGSize)size; /** setting layout properties @param layout @return chained calls are supported */ - (FBLayout *)fb_makeLayout:(void(^)(FBLayout *layout))layout; @end ================================================ FILE: FlexBoxLayout/Classes/Layout/FBViewLayoutCache.h ================================================ // // FBViewLayoutCache.h // Pods // // Created by 沈强 on 2017/3/3. // // #import @interface FBViewLayoutCache : NSObject @property(nonatomic, assign) CGRect frame; @property(nonatomic, strong) NSArray *childrenCache; @end ================================================ FILE: FlexBoxLayout/Classes/Layout/FBViewLayoutCache.m ================================================ // // FBViewLayoutCache.m // Pods // // Created by 沈强 on 2017/3/3. // // #import "FBViewLayoutCache.h" @implementation FBViewLayoutCache @end ================================================ FILE: FlexBoxLayout/Classes/Layout/YGEnums.h ================================================ /** * 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. */ #pragma once #include "YGMacros.h" YG_EXTERN_C_BEGIN typedef enum YGFlexDirection { YGFlexDirectionColumn, YGFlexDirectionColumnReverse, YGFlexDirectionRow, YGFlexDirectionRowReverse, YGFlexDirectionCount, } YGFlexDirection; typedef enum YGMeasureMode { YGMeasureModeUndefined, YGMeasureModeExactly, YGMeasureModeAtMost, YGMeasureModeCount, } YGMeasureMode; typedef enum YGPrintOptions { YGPrintOptionsLayout = 1, YGPrintOptionsStyle = 2, YGPrintOptionsChildren = 4, YGPrintOptionsCount, } YGPrintOptions; typedef enum YGEdge { YGEdgeLeft, YGEdgeTop, YGEdgeRight, YGEdgeBottom, YGEdgeStart, YGEdgeEnd, YGEdgeHorizontal, YGEdgeVertical, YGEdgeAll, YGEdgeCount, } YGEdge; typedef enum YGPositionType { YGPositionTypeRelative, YGPositionTypeAbsolute, YGPositionTypeCount, } YGPositionType; typedef enum YGDimension { YGDimensionWidth, YGDimensionHeight, YGDimensionCount, } YGDimension; typedef enum YGJustify { YGJustifyFlexStart, YGJustifyCenter, YGJustifyFlexEnd, YGJustifySpaceBetween, YGJustifySpaceAround, YGJustifyCount, } YGJustify; typedef enum YGDirection { YGDirectionInherit, YGDirectionLTR, YGDirectionRTL, YGDirectionCount, } YGDirection; typedef enum YGLogLevel { YGLogLevelError, YGLogLevelWarn, YGLogLevelInfo, YGLogLevelDebug, YGLogLevelVerbose, YGLogLevelCount, } YGLogLevel; typedef enum YGWrap { YGWrapNoWrap, YGWrapWrap, YGWrapCount, } YGWrap; typedef enum YGOverflow { YGOverflowVisible, YGOverflowHidden, YGOverflowScroll, YGOverflowCount, } YGOverflow; typedef enum YGExperimentalFeature { YGExperimentalFeatureRounding, YGExperimentalFeatureWebFlexBasis, YGExperimentalFeatureCount, } YGExperimentalFeature; typedef enum YGAlign { YGAlignAuto, YGAlignFlexStart, YGAlignCenter, YGAlignFlexEnd, YGAlignStretch, YGAlignCount, } YGAlign; YG_EXTERN_C_END ================================================ FILE: FlexBoxLayout/Classes/Layout/YGMacros.h ================================================ /** * 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. */ #pragma once #ifdef __cplusplus #define YG_EXTERN_C_BEGIN extern "C" { #define YG_EXTERN_C_END } #else #define YG_EXTERN_C_BEGIN #define YG_EXTERN_C_END #endif #ifdef _WINDLL #define WIN_EXPORT __declspec(dllexport) #else #define WIN_EXPORT #endif #ifndef FB_ASSERTIONS_ENABLED #define FB_ASSERTIONS_ENABLED 1 #endif #if FB_ASSERTIONS_ENABLED #define YG_ABORT() abort() #else #define YG_ABORT() #endif #ifndef YG_ASSERT #define YG_ASSERT(X, message) \ if (!(X)) { \ YGLog(YGLogLevelError, "%s", message); \ YG_ABORT(); \ } #endif ================================================ FILE: FlexBoxLayout/Classes/Layout/YGNodeList.c ================================================ /** * 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. */ #include "YGNodeList.h" extern YGMalloc gYGMalloc; extern YGRealloc gYGRealloc; extern YGFree gYGFree; struct YGNodeList { uint32_t capacity; uint32_t count; YGNodeRef *items; }; YGNodeListRef YGNodeListNew(const uint32_t initialCapacity) { const YGNodeListRef list = gYGMalloc(sizeof(struct YGNodeList)); YG_ASSERT(list != NULL, "Could not allocate memory for list"); list->capacity = initialCapacity; list->count = 0; list->items = gYGMalloc(sizeof(YGNodeRef) * list->capacity); YG_ASSERT(list->items != NULL, "Could not allocate memory for items"); return list; } void YGNodeListFree(const YGNodeListRef list) { if (list) { gYGFree(list->items); gYGFree(list); } } uint32_t YGNodeListCount(const YGNodeListRef list) { if (list) { return list->count; } return 0; } void YGNodeListAdd(YGNodeListRef *listp, const YGNodeRef node) { if (!*listp) { *listp = YGNodeListNew(4); } YGNodeListInsert(listp, node, (*listp)->count); } void YGNodeListInsert(YGNodeListRef *listp, const YGNodeRef node, const uint32_t index) { if (!*listp) { *listp = YGNodeListNew(4); } YGNodeListRef list = *listp; if (list->count == list->capacity) { list->capacity *= 2; list->items = gYGRealloc(list->items, sizeof(YGNodeRef) * list->capacity); YG_ASSERT(list->items != NULL, "Could not extend allocation for items"); } for (uint32_t i = list->count; i > index; i--) { list->items[i] = list->items[i - 1]; } list->count++; list->items[index] = node; } YGNodeRef YGNodeListRemove(const YGNodeListRef list, const uint32_t index) { const YGNodeRef removed = list->items[index]; list->items[index] = NULL; for (uint32_t i = index; i < list->count - 1; i++) { list->items[i] = list->items[i + 1]; list->items[i + 1] = NULL; } list->count--; return removed; } YGNodeRef YGNodeListDelete(const YGNodeListRef list, const YGNodeRef node) { for (uint32_t i = 0; i < list->count; i++) { if (list->items[i] == node) { return YGNodeListRemove(list, i); } } return NULL; } YGNodeRef YGNodeListGet(const YGNodeListRef list, const uint32_t index) { if (YGNodeListCount(list) > 0) { return list->items[index]; } return NULL; } ================================================ FILE: FlexBoxLayout/Classes/Layout/YGNodeList.h ================================================ /** * 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. */ #pragma once #include #include #include #include #include "YGMacros.h" #include "Yoga.h" YG_EXTERN_C_BEGIN typedef struct YGNodeList *YGNodeListRef; YGNodeListRef YGNodeListNew(const uint32_t initialCapacity); void YGNodeListFree(const YGNodeListRef list); uint32_t YGNodeListCount(const YGNodeListRef list); void YGNodeListAdd(YGNodeListRef *listp, const YGNodeRef node); void YGNodeListInsert(YGNodeListRef *listp, const YGNodeRef node, const uint32_t index); YGNodeRef YGNodeListRemove(const YGNodeListRef list, const uint32_t index); YGNodeRef YGNodeListDelete(const YGNodeListRef list, const YGNodeRef node); YGNodeRef YGNodeListGet(const YGNodeListRef list, const uint32_t index); YG_EXTERN_C_END ================================================ FILE: FlexBoxLayout/Classes/Layout/Yoga.c ================================================ /** * 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. */ #include #include "YGNodeList.h" #include "Yoga.h" #ifdef _MSC_VER #include #ifndef isnan #define isnan _isnan #endif #ifndef __cplusplus #define inline __inline #endif /* define fmaxf if < VC12 */ #if _MSC_VER < 1800 __forceinline const float fmaxf(const float a, const float b) { return (a > b) ? a : b; } #endif #endif typedef struct YGCachedMeasurement { float availableWidth; float availableHeight; YGMeasureMode widthMeasureMode; YGMeasureMode heightMeasureMode; float computedWidth; float computedHeight; } YGCachedMeasurement; // This value was chosen based on empiracle data. Even the most complicated // layouts should not require more than 16 entries to fit within the cache. enum { YG_MAX_CACHED_RESULT_COUNT = 16 }; typedef struct YGLayout { float position[4]; float dimensions[2]; YGDirection direction; uint32_t computedFlexBasisGeneration; float computedFlexBasis; // Instead of recomputing the entire layout every single time, we // cache some information to break early when nothing changed uint32_t generationCount; YGDirection lastParentDirection; uint32_t nextCachedMeasurementsIndex; YGCachedMeasurement cachedMeasurements[YG_MAX_CACHED_RESULT_COUNT]; float measuredDimensions[2]; YGCachedMeasurement cachedLayout; } YGLayout; typedef struct YGStyle { YGDirection direction; YGFlexDirection flexDirection; YGJustify justifyContent; YGAlign alignContent; YGAlign alignItems; YGAlign alignSelf; YGPositionType positionType; YGWrap flexWrap; YGOverflow overflow; float flex; float flexGrow; float flexShrink; float flexBasis; float margin[YGEdgeCount]; float position[YGEdgeCount]; float padding[YGEdgeCount]; float border[YGEdgeCount]; float dimensions[2]; float minDimensions[2]; float maxDimensions[2]; // Yoga specific properties, not compatible with flexbox specification float aspectRatio; } YGStyle; typedef struct YGNode { YGStyle style; YGLayout layout; uint32_t lineIndex; bool hasNewLayout; YGNodeRef parent; YGNodeListRef children; bool isDirty; struct YGNode *nextChild; YGMeasureFunc measure; YGPrintFunc print; void *context; } YGNode; static void YGNodeMarkDirtyInternal(const YGNodeRef node); YGMalloc gYGMalloc = &malloc; YGCalloc gYGCalloc = &calloc; YGRealloc gYGRealloc = &realloc; YGFree gYGFree = &free; #ifdef ANDROID #include static int YGAndroidLog(YGLogLevel level, const char *format, va_list args) { int androidLevel = YGLogLevelDebug; switch (level) { case YGLogLevelError: androidLevel = ANDROID_LOG_ERROR; break; case YGLogLevelWarn: androidLevel = ANDROID_LOG_WARN; break; case YGLogLevelInfo: androidLevel = ANDROID_LOG_INFO; break; case YGLogLevelDebug: androidLevel = ANDROID_LOG_DEBUG; break; case YGLogLevelVerbose: androidLevel = ANDROID_LOG_VERBOSE; break; case YGLogLevelCount: break; } const int result = __android_log_vprint(androidLevel, "YG-layout", format, args); return result; } static YGLogger gLogger = &YGAndroidLog; #else static int YGDefaultLog(YGLogLevel level, const char *format, va_list args) { switch (level) { case YGLogLevelError: return vfprintf(stderr, format, args); case YGLogLevelWarn: case YGLogLevelInfo: case YGLogLevelDebug: case YGLogLevelVerbose: default: return vprintf(format, args); } } static YGLogger gLogger = &YGDefaultLog; #endif static inline float YGComputedEdgeValue(const float edges[YGEdgeCount], const YGEdge edge, const float defaultValue) { YG_ASSERT(edge <= YGEdgeEnd, "Cannot get computed value of multi-edge shorthands"); if (!YGValueIsUndefined(edges[edge])) { return edges[edge]; } if ((edge == YGEdgeTop || edge == YGEdgeBottom) && !YGValueIsUndefined(edges[YGEdgeVertical])) { return edges[YGEdgeVertical]; } if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart || edge == YGEdgeEnd) && !YGValueIsUndefined(edges[YGEdgeHorizontal])) { return edges[YGEdgeHorizontal]; } if (!YGValueIsUndefined(edges[YGEdgeAll])) { return edges[YGEdgeAll]; } if (edge == YGEdgeStart || edge == YGEdgeEnd) { return YGUndefined; } return defaultValue; } static void YGNodeInit(const YGNodeRef node) { node->parent = NULL; node->children = NULL; node->hasNewLayout = true; node->isDirty = false; node->style.flex = YGUndefined; node->style.flexGrow = YGUndefined; node->style.flexShrink = YGUndefined; node->style.flexBasis = YGUndefined; node->style.alignItems = YGAlignStretch; node->style.justifyContent = YGJustifyFlexStart; node->style.alignContent = YGAlignFlexStart; node->style.direction = YGDirectionInherit; node->style.flexDirection = YGFlexDirectionColumn; node->style.overflow = YGOverflowVisible; // Some of the fields default to undefined and not 0 node->style.dimensions[YGDimensionWidth] = YGUndefined; node->style.dimensions[YGDimensionHeight] = YGUndefined; node->style.minDimensions[YGDimensionWidth] = YGUndefined; node->style.minDimensions[YGDimensionHeight] = YGUndefined; node->style.maxDimensions[YGDimensionWidth] = YGUndefined; node->style.maxDimensions[YGDimensionHeight] = YGUndefined; for (YGEdge edge = YGEdgeLeft; edge < YGEdgeCount; edge++) { node->style.position[edge] = YGUndefined; node->style.margin[edge] = YGUndefined; node->style.padding[edge] = YGUndefined; node->style.border[edge] = YGUndefined; } node->style.aspectRatio = YGUndefined; node->layout.dimensions[YGDimensionWidth] = YGUndefined; node->layout.dimensions[YGDimensionHeight] = YGUndefined; // Such that the comparison is always going to be false node->layout.lastParentDirection = (YGDirection) -1; node->layout.nextCachedMeasurementsIndex = 0; node->layout.computedFlexBasis = YGUndefined; node->layout.measuredDimensions[YGDimensionWidth] = YGUndefined; node->layout.measuredDimensions[YGDimensionHeight] = YGUndefined; node->layout.cachedLayout.widthMeasureMode = (YGMeasureMode) -1; node->layout.cachedLayout.heightMeasureMode = (YGMeasureMode) -1; node->layout.cachedLayout.computedWidth = -1; node->layout.cachedLayout.computedHeight = -1; } int32_t gNodeInstanceCount = 0; YGNodeRef YGNodeNew(void) { const YGNodeRef node = gYGCalloc(1, sizeof(YGNode)); YG_ASSERT(node, "Could not allocate memory for node"); gNodeInstanceCount++; YGNodeInit(node); return node; } void YGNodeFree(const YGNodeRef node) { if (node->parent) { YGNodeListDelete(node->parent->children, node); node->parent = NULL; } const uint32_t childCount = YGNodeGetChildCount(node); for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef child = YGNodeGetChild(node, i); child->parent = NULL; } YGNodeListFree(node->children); gYGFree(node); gNodeInstanceCount--; } void YGNodeFreeRecursive(const YGNodeRef root) { while (YGNodeGetChildCount(root) > 0) { const YGNodeRef child = YGNodeGetChild(root, 0); YGNodeRemoveChild(root, child); YGNodeFreeRecursive(child); } YGNodeFree(root); } void YGNodeReset(const YGNodeRef node) { YG_ASSERT(YGNodeGetChildCount(node) == 0, "Cannot reset a node which still has children attached"); YG_ASSERT(node->parent == NULL, "Cannot reset a node still attached to a parent"); YGNodeListFree(node->children); memset(node, 0, sizeof(YGNode)); YGNodeInit(node); } int32_t YGNodeGetInstanceCount(void) { return gNodeInstanceCount; } static void YGNodeMarkDirtyInternal(const YGNodeRef node) { if (!node->isDirty) { node->isDirty = true; node->layout.computedFlexBasis = YGUndefined; if (node->parent) { YGNodeMarkDirtyInternal(node->parent); } } } void YGNodeSetMeasureFunc(const YGNodeRef node, YGMeasureFunc measureFunc) { if (measureFunc == NULL) { node->measure = NULL; } else { YG_ASSERT(YGNodeGetChildCount(node) == 0, "Cannot set measure function: Nodes with measure functions cannot have children."); node->measure = measureFunc; } } YGMeasureFunc YGNodeGetMeasureFunc(const YGNodeRef node) { return node->measure; } void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) { YG_ASSERT(child->parent == NULL, "Child already has a parent, it must be removed first."); YG_ASSERT(node->measure == NULL, "Cannot add child: Nodes with measure functions cannot have children."); YGNodeListInsert(&node->children, child, index); child->parent = node; YGNodeMarkDirtyInternal(node); } void YGNodeRemoveChild(const YGNodeRef node, const YGNodeRef child) { if (YGNodeListDelete(node->children, child) != NULL) { child->parent = NULL; YGNodeMarkDirtyInternal(node); } } YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index) { return YGNodeListGet(node->children, index); } YGNodeRef YGNodeGetParent(const YGNodeRef node) { return node->parent; } inline uint32_t YGNodeGetChildCount(const YGNodeRef node) { return YGNodeListCount(node->children); } void YGNodeMarkDirty(const YGNodeRef node) { YG_ASSERT(node->measure != NULL, "Only leaf nodes with custom measure functions" "should manually mark themselves as dirty"); YGNodeMarkDirtyInternal(node); } bool YGNodeIsDirty(const YGNodeRef node) { return node->isDirty; } void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode) { if (memcmp(&dstNode->style, &srcNode->style, sizeof(YGStyle)) != 0) { memcpy(&dstNode->style, &srcNode->style, sizeof(YGStyle)); YGNodeMarkDirtyInternal(dstNode); } } inline float YGNodeStyleGetFlexGrow(const YGNodeRef node) { if (!YGValueIsUndefined(node->style.flexGrow)) { return node->style.flexGrow; } if (!YGValueIsUndefined(node->style.flex) && node->style.flex > 0) { return node->style.flex; } return 0; } inline float YGNodeStyleGetFlexShrink(const YGNodeRef node) { if (!YGValueIsUndefined(node->style.flexShrink)) { return node->style.flexShrink; } if (!YGValueIsUndefined(node->style.flex) && node->style.flex < 0) { return -node->style.flex; } return 0; } inline float YGNodeStyleGetFlexBasis(const YGNodeRef node) { if (!YGValueIsUndefined(node->style.flexBasis)) { return node->style.flexBasis; } if (!YGValueIsUndefined(node->style.flex)) { return node->style.flex > 0 ? 0 : YGUndefined; } return YGUndefined; } void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { if (node->style.flex != flex) { node->style.flex = flex; YGNodeMarkDirtyInternal(node); } } #define YG_NODE_PROPERTY_IMPL(type, name, paramName, instanceName) \ void YGNodeSet##name(const YGNodeRef node, type paramName) { \ node->instanceName = paramName; \ } \ \ type YGNodeGet##name(const YGNodeRef node) { \ return node->instanceName; \ } #define YG_NODE_STYLE_PROPERTY_SETTER_IMPL(type, name, paramName, instanceName) \ void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ if (node->style.instanceName != paramName) { \ node->style.instanceName = paramName; \ YGNodeMarkDirtyInternal(node); \ } \ } #define YG_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \ YG_NODE_STYLE_PROPERTY_SETTER_IMPL(type, name, paramName, instanceName) \ \ type YGNodeStyleGet##name(const YGNodeRef node) { \ return node->style.instanceName; \ } #define YG_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName, defaultValue) \ void YGNodeStyleSet##name(const YGNodeRef node, const YGEdge edge, const type paramName) { \ if (node->style.instanceName[edge] != paramName) { \ node->style.instanceName[edge] = paramName; \ YGNodeMarkDirtyInternal(node); \ } \ } \ \ type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ return YGComputedEdgeValue(node->style.instanceName, edge, defaultValue); \ } #define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \ type YGNodeLayoutGet##name(const YGNodeRef node) { \ return node->layout.instanceName; \ } YG_NODE_PROPERTY_IMPL(void *, Context, context, context); YG_NODE_PROPERTY_IMPL(YGPrintFunc, PrintFunc, printFunc, print); YG_NODE_PROPERTY_IMPL(bool, HasNewLayout, hasNewLayout, hasNewLayout); YG_NODE_STYLE_PROPERTY_IMPL(YGDirection, Direction, direction, direction); YG_NODE_STYLE_PROPERTY_IMPL(YGFlexDirection, FlexDirection, flexDirection, flexDirection); YG_NODE_STYLE_PROPERTY_IMPL(YGJustify, JustifyContent, justifyContent, justifyContent); YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignContent, alignContent, alignContent); YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignItems, alignItems, alignItems); YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignSelf, alignSelf, alignSelf); YG_NODE_STYLE_PROPERTY_IMPL(YGPositionType, PositionType, positionType, positionType); YG_NODE_STYLE_PROPERTY_IMPL(YGWrap, FlexWrap, flexWrap, flexWrap); YG_NODE_STYLE_PROPERTY_IMPL(YGOverflow, Overflow, overflow, overflow); YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexGrow, flexGrow, flexGrow); YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexShrink, flexShrink, flexShrink); YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexBasis, flexBasis, flexBasis); YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Position, position, position, YGUndefined); YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Margin, margin, margin, 0); YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Padding, padding, padding, 0); YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Border, border, border, 0); YG_NODE_STYLE_PROPERTY_IMPL(float, Width, width, dimensions[YGDimensionWidth]); YG_NODE_STYLE_PROPERTY_IMPL(float, Height, height, dimensions[YGDimensionHeight]); YG_NODE_STYLE_PROPERTY_IMPL(float, MinWidth, minWidth, minDimensions[YGDimensionWidth]); YG_NODE_STYLE_PROPERTY_IMPL(float, MinHeight, minHeight, minDimensions[YGDimensionHeight]); YG_NODE_STYLE_PROPERTY_IMPL(float, MaxWidth, maxWidth, maxDimensions[YGDimensionWidth]); YG_NODE_STYLE_PROPERTY_IMPL(float, MaxHeight, maxHeight, maxDimensions[YGDimensionHeight]); // Yoga specific properties, not compatible with flexbox specification YG_NODE_STYLE_PROPERTY_IMPL(float, AspectRatio, aspectRatio, aspectRatio); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Bottom, position[YGEdgeBottom]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Width, dimensions[YGDimensionWidth]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Height, dimensions[YGDimensionHeight]); YG_NODE_LAYOUT_PROPERTY_IMPL(YGDirection, Direction, direction); uint32_t gCurrentGenerationCount = 0; bool YGLayoutNodeInternal(const YGNodeRef node, const float availableWidth, const float availableHeight, const YGDirection parentDirection, const YGMeasureMode widthMeasureMode, const YGMeasureMode heightMeasureMode, const bool performLayout, const char *reason); inline bool YGValueIsUndefined(const float value) { return isnan(value); } static inline bool YGFloatsEqual(const float a, const float b) { if (YGValueIsUndefined(a)) { return YGValueIsUndefined(b); } return fabs(a - b) < 0.0001; } static void YGIndent(const uint32_t n) { for (uint32_t i = 0; i < n; i++) { YGLog(YGLogLevelDebug, " "); } } static void YGPrintNumberIfNotZero(const char *str, const float number) { if (!YGFloatsEqual(number, 0)) { YGLog(YGLogLevelDebug, "%s: %g, ", str, number); } } static void YGPrintNumberIfNotUndefined(const char *str, const float number) { if (!YGValueIsUndefined(number)) { YGLog(YGLogLevelDebug, "%s: %g, ", str, number); } } static bool YGFourFloatsEqual(const float four[4]) { return YGFloatsEqual(four[0], four[1]) && YGFloatsEqual(four[0], four[2]) && YGFloatsEqual(four[0], four[3]); } static void YGNodePrintInternal(const YGNodeRef node, const YGPrintOptions options, const uint32_t level) { YGIndent(level); YGLog(YGLogLevelDebug, "{"); if (node->print) { node->print(node); } if (options & YGPrintOptionsLayout) { YGLog(YGLogLevelDebug, "layout: {"); YGLog(YGLogLevelDebug, "width: %g, ", node->layout.dimensions[YGDimensionWidth]); YGLog(YGLogLevelDebug, "height: %g, ", node->layout.dimensions[YGDimensionHeight]); YGLog(YGLogLevelDebug, "top: %g, ", node->layout.position[YGEdgeTop]); YGLog(YGLogLevelDebug, "left: %g", node->layout.position[YGEdgeLeft]); YGLog(YGLogLevelDebug, "}, "); } if (options & YGPrintOptionsStyle) { if (node->style.flexDirection == YGFlexDirectionColumn) { YGLog(YGLogLevelDebug, "flexDirection: 'column', "); } else if (node->style.flexDirection == YGFlexDirectionColumnReverse) { YGLog(YGLogLevelDebug, "flexDirection: 'column-reverse', "); } else if (node->style.flexDirection == YGFlexDirectionRow) { YGLog(YGLogLevelDebug, "flexDirection: 'row', "); } else if (node->style.flexDirection == YGFlexDirectionRowReverse) { YGLog(YGLogLevelDebug, "flexDirection: 'row-reverse', "); } if (node->style.justifyContent == YGJustifyCenter) { YGLog(YGLogLevelDebug, "justifyContent: 'center', "); } else if (node->style.justifyContent == YGJustifyFlexEnd) { YGLog(YGLogLevelDebug, "justifyContent: 'flex-end', "); } else if (node->style.justifyContent == YGJustifySpaceAround) { YGLog(YGLogLevelDebug, "justifyContent: 'space-around', "); } else if (node->style.justifyContent == YGJustifySpaceBetween) { YGLog(YGLogLevelDebug, "justifyContent: 'space-between', "); } if (node->style.alignItems == YGAlignCenter) { YGLog(YGLogLevelDebug, "alignItems: 'center', "); } else if (node->style.alignItems == YGAlignFlexEnd) { YGLog(YGLogLevelDebug, "alignItems: 'flex-end', "); } else if (node->style.alignItems == YGAlignStretch) { YGLog(YGLogLevelDebug, "alignItems: 'stretch', "); } if (node->style.alignContent == YGAlignCenter) { YGLog(YGLogLevelDebug, "alignContent: 'center', "); } else if (node->style.alignContent == YGAlignFlexEnd) { YGLog(YGLogLevelDebug, "alignContent: 'flex-end', "); } else if (node->style.alignContent == YGAlignStretch) { YGLog(YGLogLevelDebug, "alignContent: 'stretch', "); } if (node->style.alignSelf == YGAlignFlexStart) { YGLog(YGLogLevelDebug, "alignSelf: 'flex-start', "); } else if (node->style.alignSelf == YGAlignCenter) { YGLog(YGLogLevelDebug, "alignSelf: 'center', "); } else if (node->style.alignSelf == YGAlignFlexEnd) { YGLog(YGLogLevelDebug, "alignSelf: 'flex-end', "); } else if (node->style.alignSelf == YGAlignStretch) { YGLog(YGLogLevelDebug, "alignSelf: 'stretch', "); } YGPrintNumberIfNotUndefined("flexGrow", YGNodeStyleGetFlexGrow(node)); YGPrintNumberIfNotUndefined("flexShrink", YGNodeStyleGetFlexShrink(node)); YGPrintNumberIfNotUndefined("flexBasis", YGNodeStyleGetFlexBasis(node)); if (node->style.overflow == YGOverflowHidden) { YGLog(YGLogLevelDebug, "overflow: 'hidden', "); } else if (node->style.overflow == YGOverflowVisible) { YGLog(YGLogLevelDebug, "overflow: 'visible', "); } else if (node->style.overflow == YGOverflowScroll) { YGLog(YGLogLevelDebug, "overflow: 'scroll', "); } if (YGFourFloatsEqual(node->style.margin)) { YGPrintNumberIfNotZero("margin", YGComputedEdgeValue(node->style.margin, YGEdgeLeft, 0)); } else { YGPrintNumberIfNotZero("marginLeft", YGComputedEdgeValue(node->style.margin, YGEdgeLeft, 0)); YGPrintNumberIfNotZero("marginRight", YGComputedEdgeValue(node->style.margin, YGEdgeRight, 0)); YGPrintNumberIfNotZero("marginTop", YGComputedEdgeValue(node->style.margin, YGEdgeTop, 0)); YGPrintNumberIfNotZero("marginBottom", YGComputedEdgeValue(node->style.margin, YGEdgeBottom, 0)); YGPrintNumberIfNotZero("marginStart", YGComputedEdgeValue(node->style.margin, YGEdgeStart, 0)); YGPrintNumberIfNotZero("marginEnd", YGComputedEdgeValue(node->style.margin, YGEdgeEnd, 0)); } if (YGFourFloatsEqual(node->style.padding)) { YGPrintNumberIfNotZero("padding", YGComputedEdgeValue(node->style.padding, YGEdgeLeft, 0)); } else { YGPrintNumberIfNotZero("paddingLeft", YGComputedEdgeValue(node->style.padding, YGEdgeLeft, 0)); YGPrintNumberIfNotZero("paddingRight", YGComputedEdgeValue(node->style.padding, YGEdgeRight, 0)); YGPrintNumberIfNotZero("paddingTop", YGComputedEdgeValue(node->style.padding, YGEdgeTop, 0)); YGPrintNumberIfNotZero("paddingBottom", YGComputedEdgeValue(node->style.padding, YGEdgeBottom, 0)); YGPrintNumberIfNotZero("paddingStart", YGComputedEdgeValue(node->style.padding, YGEdgeStart, 0)); YGPrintNumberIfNotZero("paddingEnd", YGComputedEdgeValue(node->style.padding, YGEdgeEnd, 0)); } if (YGFourFloatsEqual(node->style.border)) { YGPrintNumberIfNotZero("borderWidth", YGComputedEdgeValue(node->style.border, YGEdgeLeft, 0)); } else { YGPrintNumberIfNotZero("borderLeftWidth", YGComputedEdgeValue(node->style.border, YGEdgeLeft, 0)); YGPrintNumberIfNotZero("borderRightWidth", YGComputedEdgeValue(node->style.border, YGEdgeRight, 0)); YGPrintNumberIfNotZero("borderTopWidth", YGComputedEdgeValue(node->style.border, YGEdgeTop, 0)); YGPrintNumberIfNotZero("borderBottomWidth", YGComputedEdgeValue(node->style.border, YGEdgeBottom, 0)); YGPrintNumberIfNotZero("borderStartWidth", YGComputedEdgeValue(node->style.border, YGEdgeStart, 0)); YGPrintNumberIfNotZero("borderEndWidth", YGComputedEdgeValue(node->style.border, YGEdgeEnd, 0)); } YGPrintNumberIfNotUndefined("width", node->style.dimensions[YGDimensionWidth]); YGPrintNumberIfNotUndefined("height", node->style.dimensions[YGDimensionHeight]); YGPrintNumberIfNotUndefined("maxWidth", node->style.maxDimensions[YGDimensionWidth]); YGPrintNumberIfNotUndefined("maxHeight", node->style.maxDimensions[YGDimensionHeight]); YGPrintNumberIfNotUndefined("minWidth", node->style.minDimensions[YGDimensionWidth]); YGPrintNumberIfNotUndefined("minHeight", node->style.minDimensions[YGDimensionHeight]); if (node->style.positionType == YGPositionTypeAbsolute) { YGLog(YGLogLevelDebug, "position: 'absolute', "); } YGPrintNumberIfNotUndefined("left", YGComputedEdgeValue(node->style.position, YGEdgeLeft, YGUndefined)); YGPrintNumberIfNotUndefined( "right", YGComputedEdgeValue(node->style.position, YGEdgeRight, YGUndefined)); YGPrintNumberIfNotUndefined("top", YGComputedEdgeValue(node->style.position, YGEdgeTop, YGUndefined)); YGPrintNumberIfNotUndefined( "bottom", YGComputedEdgeValue(node->style.position, YGEdgeBottom, YGUndefined)); } const uint32_t childCount = YGNodeListCount(node->children); if (options & YGPrintOptionsChildren && childCount > 0) { YGLog(YGLogLevelDebug, "children: [\n"); for (uint32_t i = 0; i < childCount; i++) { YGNodePrintInternal(YGNodeGetChild(node, i), options, level + 1); } YGIndent(level); YGLog(YGLogLevelDebug, "]},\n"); } else { YGLog(YGLogLevelDebug, "},\n"); } } void YGNodePrint(const YGNodeRef node, const YGPrintOptions options) { YGNodePrintInternal(node, options, 0); } static const YGEdge leading[4] = { [YGFlexDirectionColumn] = YGEdgeTop, [YGFlexDirectionColumnReverse] = YGEdgeBottom, [YGFlexDirectionRow] = YGEdgeLeft, [YGFlexDirectionRowReverse] = YGEdgeRight, }; static const YGEdge trailing[4] = { [YGFlexDirectionColumn] = YGEdgeBottom, [YGFlexDirectionColumnReverse] = YGEdgeTop, [YGFlexDirectionRow] = YGEdgeRight, [YGFlexDirectionRowReverse] = YGEdgeLeft, }; static const YGEdge pos[4] = { [YGFlexDirectionColumn] = YGEdgeTop, [YGFlexDirectionColumnReverse] = YGEdgeBottom, [YGFlexDirectionRow] = YGEdgeLeft, [YGFlexDirectionRowReverse] = YGEdgeRight, }; static const YGDimension dim[4] = { [YGFlexDirectionColumn] = YGDimensionHeight, [YGFlexDirectionColumnReverse] = YGDimensionHeight, [YGFlexDirectionRow] = YGDimensionWidth, [YGFlexDirectionRowReverse] = YGDimensionWidth, }; static inline bool YGFlexDirectionIsRow(const YGFlexDirection flexDirection) { return flexDirection == YGFlexDirectionRow || flexDirection == YGFlexDirectionRowReverse; } static inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) { return flexDirection == YGFlexDirectionColumn || flexDirection == YGFlexDirectionColumnReverse; } static inline float YGNodeLeadingMargin(const YGNodeRef node, const YGFlexDirection axis) { if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.margin[YGEdgeStart])) { return node->style.margin[YGEdgeStart]; } return YGComputedEdgeValue(node->style.margin, leading[axis], 0); } static float YGNodeTrailingMargin(const YGNodeRef node, const YGFlexDirection axis) { if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.margin[YGEdgeEnd])) { return node->style.margin[YGEdgeEnd]; } return YGComputedEdgeValue(node->style.margin, trailing[axis], 0); } static float YGNodeLeadingPadding(const YGNodeRef node, const YGFlexDirection axis) { if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.padding[YGEdgeStart]) && node->style.padding[YGEdgeStart] >= 0) { return node->style.padding[YGEdgeStart]; } return fmaxf(YGComputedEdgeValue(node->style.padding, leading[axis], 0), 0); } static float YGNodeTrailingPadding(const YGNodeRef node, const YGFlexDirection axis) { if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.padding[YGEdgeEnd]) && node->style.padding[YGEdgeEnd] >= 0) { return node->style.padding[YGEdgeEnd]; } return fmaxf(YGComputedEdgeValue(node->style.padding, trailing[axis], 0), 0); } static float YGNodeLeadingBorder(const YGNodeRef node, const YGFlexDirection axis) { if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.border[YGEdgeStart]) && node->style.border[YGEdgeStart] >= 0) { return node->style.border[YGEdgeStart]; } return fmaxf(YGComputedEdgeValue(node->style.border, leading[axis], 0), 0); } static float YGNodeTrailingBorder(const YGNodeRef node, const YGFlexDirection axis) { if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.border[YGEdgeEnd]) && node->style.border[YGEdgeEnd] >= 0) { return node->style.border[YGEdgeEnd]; } return fmaxf(YGComputedEdgeValue(node->style.border, trailing[axis], 0), 0); } static inline float YGNodeLeadingPaddingAndBorder(const YGNodeRef node, const YGFlexDirection axis) { return YGNodeLeadingPadding(node, axis) + YGNodeLeadingBorder(node, axis); } static inline float YGNodeTrailingPaddingAndBorder(const YGNodeRef node, const YGFlexDirection axis) { return YGNodeTrailingPadding(node, axis) + YGNodeTrailingBorder(node, axis); } static inline float YGNodeMarginForAxis(const YGNodeRef node, const YGFlexDirection axis) { return YGNodeLeadingMargin(node, axis) + YGNodeTrailingMargin(node, axis); } static inline float YGNodePaddingAndBorderForAxis(const YGNodeRef node, const YGFlexDirection axis) { return YGNodeLeadingPaddingAndBorder(node, axis) + YGNodeTrailingPaddingAndBorder(node, axis); } static inline YGAlign YGNodeAlignItem(const YGNodeRef node, const YGNodeRef child) { return child->style.alignSelf == YGAlignAuto ? node->style.alignItems : child->style.alignSelf; } static inline YGDirection YGNodeResolveDirection(const YGNodeRef node, const YGDirection parentDirection) { if (node->style.direction == YGDirectionInherit) { return parentDirection > YGDirectionInherit ? parentDirection : YGDirectionLTR; } else { return node->style.direction; } } static inline YGFlexDirection YGFlexDirectionResolve(const YGFlexDirection flexDirection, const YGDirection direction) { if (direction == YGDirectionRTL) { if (flexDirection == YGFlexDirectionRow) { return YGFlexDirectionRowReverse; } else if (flexDirection == YGFlexDirectionRowReverse) { return YGFlexDirectionRow; } } return flexDirection; } static YGFlexDirection YGFlexDirectionCross(const YGFlexDirection flexDirection, const YGDirection direction) { return YGFlexDirectionIsColumn(flexDirection) ? YGFlexDirectionResolve(YGFlexDirectionRow, direction) : YGFlexDirectionColumn; } static inline bool YGNodeIsFlex(const YGNodeRef node) { return (node->style.positionType == YGPositionTypeRelative && (node->style.flexGrow != 0 || node->style.flexShrink != 0 || node->style.flex != 0)); } static inline float YGNodeDimWithMargin(const YGNodeRef node, const YGFlexDirection axis) { return node->layout.measuredDimensions[dim[axis]] + YGNodeLeadingMargin(node, axis) + YGNodeTrailingMargin(node, axis); } static inline bool YGNodeIsStyleDimDefined(const YGNodeRef node, const YGFlexDirection axis) { const float value = node->style.dimensions[dim[axis]]; return !YGValueIsUndefined(value) && value >= 0.0; } static inline bool YGNodeIsLayoutDimDefined(const YGNodeRef node, const YGFlexDirection axis) { const float value = node->layout.measuredDimensions[dim[axis]]; return !YGValueIsUndefined(value) && value >= 0.0; } static inline bool YGNodeIsLeadingPosDefined(const YGNodeRef node, const YGFlexDirection axis) { return (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined( YGComputedEdgeValue(node->style.position, YGEdgeStart, YGUndefined))) || !YGValueIsUndefined(YGComputedEdgeValue(node->style.position, leading[axis], YGUndefined)); } static inline bool YGNodeIsTrailingPosDefined(const YGNodeRef node, const YGFlexDirection axis) { return (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(YGComputedEdgeValue(node->style.position, YGEdgeEnd, YGUndefined))) || !YGValueIsUndefined( YGComputedEdgeValue(node->style.position, trailing[axis], YGUndefined)); } static float YGNodeLeadingPosition(const YGNodeRef node, const YGFlexDirection axis) { if (YGFlexDirectionIsRow(axis)) { const float leadingPosition = YGComputedEdgeValue(node->style.position, YGEdgeStart, YGUndefined); if (!YGValueIsUndefined(leadingPosition)) { return leadingPosition; } } const float leadingPosition = YGComputedEdgeValue(node->style.position, leading[axis], YGUndefined); return YGValueIsUndefined(leadingPosition) ? 0 : leadingPosition; } static float YGNodeTrailingPosition(const YGNodeRef node, const YGFlexDirection axis) { if (YGFlexDirectionIsRow(axis)) { const float trailingPosition = YGComputedEdgeValue(node->style.position, YGEdgeEnd, YGUndefined); if (!YGValueIsUndefined(trailingPosition)) { return trailingPosition; } } const float trailingPosition = YGComputedEdgeValue(node->style.position, trailing[axis], YGUndefined); return YGValueIsUndefined(trailingPosition) ? 0 : trailingPosition; } static float YGNodeBoundAxisWithinMinAndMax(const YGNodeRef node, const YGFlexDirection axis, const float value) { float min = YGUndefined; float max = YGUndefined; if (YGFlexDirectionIsColumn(axis)) { min = node->style.minDimensions[YGDimensionHeight]; max = node->style.maxDimensions[YGDimensionHeight]; } else if (YGFlexDirectionIsRow(axis)) { min = node->style.minDimensions[YGDimensionWidth]; max = node->style.maxDimensions[YGDimensionWidth]; } float boundValue = value; if (!YGValueIsUndefined(max) && max >= 0.0 && boundValue > max) { boundValue = max; } if (!YGValueIsUndefined(min) && min >= 0.0 && boundValue < min) { boundValue = min; } return boundValue; } // Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't go // below the // padding and border amount. static inline float YGNodeBoundAxis(const YGNodeRef node, const YGFlexDirection axis, const float value) { return fmaxf(YGNodeBoundAxisWithinMinAndMax(node, axis, value), YGNodePaddingAndBorderForAxis(node, axis)); } static void YGNodeSetChildTrailingPosition(const YGNodeRef node, const YGNodeRef child, const YGFlexDirection axis) { const float size = child->layout.measuredDimensions[dim[axis]]; child->layout.position[trailing[axis]] = node->layout.measuredDimensions[dim[axis]] - size - child->layout.position[pos[axis]]; } // If both left and right are defined, then use left. Otherwise return // +left or -right depending on which is defined. static float YGNodeRelativePosition(const YGNodeRef node, const YGFlexDirection axis) { return YGNodeIsLeadingPosDefined(node, axis) ? YGNodeLeadingPosition(node, axis) : -YGNodeTrailingPosition(node, axis); } static void YGConstrainMaxSizeForMode(const float maxSize, YGMeasureMode *mode, float *size) { switch (*mode) { case YGMeasureModeExactly: case YGMeasureModeAtMost: *size = (YGValueIsUndefined(maxSize) || *size < maxSize) ? *size : maxSize; break; case YGMeasureModeUndefined: if (!YGValueIsUndefined(maxSize)) { *mode = YGMeasureModeAtMost; *size = maxSize; } break; case YGMeasureModeCount: break; } } static void YGNodeSetPosition(const YGNodeRef node, const YGDirection direction) { const YGFlexDirection mainAxis = YGFlexDirectionResolve(node->style.flexDirection, direction); const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction); const float relativePositionMain = YGNodeRelativePosition(node, mainAxis); const float relativePositionCross = YGNodeRelativePosition(node, crossAxis); node->layout.position[leading[mainAxis]] = YGNodeLeadingMargin(node, mainAxis) + relativePositionMain; node->layout.position[trailing[mainAxis]] = YGNodeTrailingMargin(node, mainAxis) + relativePositionMain; node->layout.position[leading[crossAxis]] = YGNodeLeadingMargin(node, crossAxis) + relativePositionCross; node->layout.position[trailing[crossAxis]] = YGNodeTrailingMargin(node, crossAxis) + relativePositionCross; } static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, const YGNodeRef child, const float width, const YGMeasureMode widthMode, const float height, const YGMeasureMode heightMode, const YGDirection direction) { const YGFlexDirection mainAxis = YGFlexDirectionResolve(node->style.flexDirection, direction); const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis); float childWidth; float childHeight; YGMeasureMode childWidthMeasureMode; YGMeasureMode childHeightMeasureMode; const bool isRowStyleDimDefined = YGNodeIsStyleDimDefined(child, YGFlexDirectionRow); const bool isColumnStyleDimDefined = YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn); if (!YGValueIsUndefined(YGNodeStyleGetFlexBasis(child)) && !YGValueIsUndefined(isMainAxisRow ? width : height)) { if (YGValueIsUndefined(child->layout.computedFlexBasis) || (YGIsExperimentalFeatureEnabled(YGExperimentalFeatureWebFlexBasis) && child->layout.computedFlexBasisGeneration != gCurrentGenerationCount)) { child->layout.computedFlexBasis = fmaxf(YGNodeStyleGetFlexBasis(child), YGNodePaddingAndBorderForAxis(child, mainAxis)); } } else if (isMainAxisRow && isRowStyleDimDefined) { // The width is definite, so use that as the flex basis. child->layout.computedFlexBasis = fmaxf(child->style.dimensions[YGDimensionWidth], YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow)); } else if (!isMainAxisRow && isColumnStyleDimDefined) { // The height is definite, so use that as the flex basis. child->layout.computedFlexBasis = fmaxf(child->style.dimensions[YGDimensionHeight], YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn)); } else { // Compute the flex basis and hypothetical main size (i.e. the clamped // flex basis). childWidth = YGUndefined; childHeight = YGUndefined; childWidthMeasureMode = YGMeasureModeUndefined; childHeightMeasureMode = YGMeasureModeUndefined; if (isRowStyleDimDefined) { childWidth = child->style.dimensions[YGDimensionWidth] + YGNodeMarginForAxis(child, YGFlexDirectionRow); childWidthMeasureMode = YGMeasureModeExactly; } if (isColumnStyleDimDefined) { childHeight = child->style.dimensions[YGDimensionHeight] + YGNodeMarginForAxis(child, YGFlexDirectionColumn); childHeightMeasureMode = YGMeasureModeExactly; } // The W3C spec doesn't say anything about the 'overflow' property, // but all major browsers appear to implement the following logic. if ((!isMainAxisRow && node->style.overflow == YGOverflowScroll) || node->style.overflow != YGOverflowScroll) { if (YGValueIsUndefined(childWidth) && !YGValueIsUndefined(width)) { childWidth = width; childWidthMeasureMode = YGMeasureModeAtMost; } } if ((isMainAxisRow && node->style.overflow == YGOverflowScroll) || node->style.overflow != YGOverflowScroll) { if (YGValueIsUndefined(childHeight) && !YGValueIsUndefined(height)) { childHeight = height; childHeightMeasureMode = YGMeasureModeAtMost; } } // If child has no defined size in the cross axis and is set to stretch, // set the cross // axis to be measured exactly with the available inner width if (!isMainAxisRow && !YGValueIsUndefined(width) && !isRowStyleDimDefined && widthMode == YGMeasureModeExactly && YGNodeAlignItem(node, child) == YGAlignStretch) { childWidth = width; childWidthMeasureMode = YGMeasureModeExactly; } if (isMainAxisRow && !YGValueIsUndefined(height) && !isColumnStyleDimDefined && heightMode == YGMeasureModeExactly && YGNodeAlignItem(node, child) == YGAlignStretch) { childHeight = height; childHeightMeasureMode = YGMeasureModeExactly; } if (!YGValueIsUndefined(child->style.aspectRatio)) { if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) { child->layout.computedFlexBasis = fmaxf(childWidth * child->style.aspectRatio, YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn)); return; } else if (isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) { child->layout.computedFlexBasis = fmaxf(childHeight * child->style.aspectRatio, YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow)); return; } } YGConstrainMaxSizeForMode(child->style.maxDimensions[YGDimensionWidth], &childWidthMeasureMode, &childWidth); YGConstrainMaxSizeForMode(child->style.maxDimensions[YGDimensionHeight], &childHeightMeasureMode, &childHeight); // Measure the child YGLayoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "measure"); child->layout.computedFlexBasis = fmaxf(isMainAxisRow ? child->layout.measuredDimensions[YGDimensionWidth] : child->layout.measuredDimensions[YGDimensionHeight], YGNodePaddingAndBorderForAxis(child, mainAxis)); } child->layout.computedFlexBasisGeneration = gCurrentGenerationCount; } static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, const YGNodeRef child, const float width, const YGMeasureMode widthMode, const YGDirection direction) { const YGFlexDirection mainAxis = YGFlexDirectionResolve(node->style.flexDirection, direction); const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction); const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis); float childWidth = YGUndefined; float childHeight = YGUndefined; YGMeasureMode childWidthMeasureMode = YGMeasureModeUndefined; YGMeasureMode childHeightMeasureMode = YGMeasureModeUndefined; if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow)) { childWidth = child->style.dimensions[YGDimensionWidth] + YGNodeMarginForAxis(child, YGFlexDirectionRow); } else { // If the child doesn't have a specified width, compute the width based // on the left/right // offsets if they're defined. if (YGNodeIsLeadingPosDefined(child, YGFlexDirectionRow) && YGNodeIsTrailingPosDefined(child, YGFlexDirectionRow)) { childWidth = node->layout.measuredDimensions[YGDimensionWidth] - (YGNodeLeadingBorder(node, YGFlexDirectionRow) + YGNodeTrailingBorder(node, YGFlexDirectionRow)) - (YGNodeLeadingPosition(child, YGFlexDirectionRow) + YGNodeTrailingPosition(child, YGFlexDirectionRow)); childWidth = YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth); } } if (YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn)) { childHeight = child->style.dimensions[YGDimensionHeight] + YGNodeMarginForAxis(child, YGFlexDirectionColumn); } else { // If the child doesn't have a specified height, compute the height // based on the top/bottom // offsets if they're defined. if (YGNodeIsLeadingPosDefined(child, YGFlexDirectionColumn) && YGNodeIsTrailingPosDefined(child, YGFlexDirectionColumn)) { childHeight = node->layout.measuredDimensions[YGDimensionHeight] - (YGNodeLeadingBorder(node, YGFlexDirectionColumn) + YGNodeTrailingBorder(node, YGFlexDirectionColumn)) - (YGNodeLeadingPosition(child, YGFlexDirectionColumn) + YGNodeTrailingPosition(child, YGFlexDirectionColumn)); childHeight = YGNodeBoundAxis(child, YGFlexDirectionColumn, childHeight); } } // Exactly one dimension needs to be defined for us to be able to do aspect ratio // calculation. One dimension being the anchor and the other being flexible. if (YGValueIsUndefined(childWidth) ^ YGValueIsUndefined(childHeight)) { if (!YGValueIsUndefined(child->style.aspectRatio)) { if (YGValueIsUndefined(childWidth)) { childWidth = fmaxf(childHeight * child->style.aspectRatio, YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn)); } else if (YGValueIsUndefined(childHeight)) { childHeight = fmaxf(childWidth * child->style.aspectRatio, YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow)); } } } // If we're still missing one or the other dimension, measure the content. if (YGValueIsUndefined(childWidth) || YGValueIsUndefined(childHeight)) { childWidthMeasureMode = YGValueIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly; childHeightMeasureMode = YGValueIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly; // According to the spec, if the main size is not definite and the // child's inline axis is parallel to the main axis (i.e. it's // horizontal), the child should be sized using "UNDEFINED" in // the main size. Otherwise use "AT_MOST" in the cross axis. if (!isMainAxisRow && YGValueIsUndefined(childWidth) && widthMode != YGMeasureModeUndefined) { childWidth = width; childWidthMeasureMode = YGMeasureModeAtMost; } YGLayoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "abs-measure"); childWidth = child->layout.measuredDimensions[YGDimensionWidth] + YGNodeMarginForAxis(child, YGFlexDirectionRow); childHeight = child->layout.measuredDimensions[YGDimensionHeight] + YGNodeMarginForAxis(child, YGFlexDirectionColumn); } YGLayoutNodeInternal(child, childWidth, childHeight, direction, YGMeasureModeExactly, YGMeasureModeExactly, true, "abs-layout"); if (YGNodeIsTrailingPosDefined(child, mainAxis) && !YGNodeIsLeadingPosDefined(child, mainAxis)) { child->layout.position[leading[mainAxis]] = node->layout.measuredDimensions[dim[mainAxis]] - child->layout.measuredDimensions[dim[mainAxis]] - YGNodeTrailingBorder(node, mainAxis) - YGNodeTrailingPosition(child, mainAxis); } if (YGNodeIsTrailingPosDefined(child, crossAxis) && !YGNodeIsLeadingPosDefined(child, crossAxis)) { child->layout.position[leading[crossAxis]] = node->layout.measuredDimensions[dim[crossAxis]] - child->layout.measuredDimensions[dim[crossAxis]] - YGNodeTrailingBorder(node, crossAxis) - YGNodeTrailingPosition(child, crossAxis); } } static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node, const float availableWidth, const float availableHeight, const YGMeasureMode widthMeasureMode, const YGMeasureMode heightMeasureMode) { YG_ASSERT(node->measure, "Expected node to have custom measure function"); const float paddingAndBorderAxisRow = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow); const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn); const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow); const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); const float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow; const float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn; if (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly) { // Don't bother sizing the text if both dimensions are already defined. node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis(node, YGFlexDirectionRow, availableWidth - marginAxisRow); node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(node, YGFlexDirectionColumn, availableHeight - marginAxisColumn); } else if (innerWidth <= 0 || innerHeight <= 0) { // Don't bother sizing the text if there's no horizontal or vertical // space. node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis(node, YGFlexDirectionRow, 0); node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(node, YGFlexDirectionColumn, 0); } else { // Measure the text under the current constraints. const YGSize measuredSize = node->measure(node, innerWidth, widthMeasureMode, innerHeight, heightMeasureMode); node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis(node, YGFlexDirectionRow, (widthMeasureMode == YGMeasureModeUndefined || widthMeasureMode == YGMeasureModeAtMost) ? measuredSize.width + paddingAndBorderAxisRow : availableWidth - marginAxisRow); node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(node, YGFlexDirectionColumn, (heightMeasureMode == YGMeasureModeUndefined || heightMeasureMode == YGMeasureModeAtMost) ? measuredSize.height + paddingAndBorderAxisColumn : availableHeight - marginAxisColumn); } } // For nodes with no children, use the available values if they were provided, // or the minimum size as indicated by the padding and border sizes. static void YGNodeEmptyContainerSetMeasuredDimensions(const YGNodeRef node, const float availableWidth, const float availableHeight, const YGMeasureMode widthMeasureMode, const YGMeasureMode heightMeasureMode) { const float paddingAndBorderAxisRow = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow); const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn); const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow); const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis(node, YGFlexDirectionRow, (widthMeasureMode == YGMeasureModeUndefined || widthMeasureMode == YGMeasureModeAtMost) ? paddingAndBorderAxisRow : availableWidth - marginAxisRow); node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(node, YGFlexDirectionColumn, (heightMeasureMode == YGMeasureModeUndefined || heightMeasureMode == YGMeasureModeAtMost) ? paddingAndBorderAxisColumn : availableHeight - marginAxisColumn); } static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node, const float availableWidth, const float availableHeight, const YGMeasureMode widthMeasureMode, const YGMeasureMode heightMeasureMode) { if ((widthMeasureMode == YGMeasureModeAtMost && availableWidth <= 0) || (heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0) || (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly)) { const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow); node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis(node, YGFlexDirectionRow, YGValueIsUndefined(availableWidth) || (widthMeasureMode == YGMeasureModeAtMost && availableWidth < 0) ? 0 : availableWidth - marginAxisRow); node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(node, YGFlexDirectionColumn, YGValueIsUndefined(availableHeight) || (heightMeasureMode == YGMeasureModeAtMost && availableHeight < 0) ? 0 : availableHeight - marginAxisColumn); return true; } return false; } // // This is the main routine that implements a subset of the flexbox layout // algorithm // described in the W3C YG documentation: https://www.w3.org/TR/YG3-flexbox/. // // Limitations of this algorithm, compared to the full standard: // * Display property is always assumed to be 'flex' except for Text nodes, // which // are assumed to be 'inline-flex'. // * The 'zIndex' property (or any form of z ordering) is not supported. Nodes // are // stacked in document order. // * The 'order' property is not supported. The order of flex items is always // defined // by document order. // * The 'visibility' property is always assumed to be 'visible'. Values of // 'collapse' // and 'hidden' are not supported. // * The 'wrap' property supports only 'nowrap' (which is the default) or // 'wrap'. The // rarely-used 'wrap-reverse' is not supported. // * Rather than allowing arbitrary combinations of flexGrow, flexShrink and // flexBasis, this algorithm supports only the three most common // combinations: // flex: 0 is equiavlent to flex: 0 0 auto // flex: n (where n is a positive value) is equivalent to flex: n 1 auto // If POSITIVE_FLEX_IS_AUTO is 0, then it is equivalent to flex: n 0 0 // This is faster because the content doesn't need to be measured, but // it's // less flexible because the basis is always 0 and can't be overriden // with // the width/height attributes. // flex: -1 (or any negative value) is equivalent to flex: 0 1 auto // * Margins cannot be specified as 'auto'. They must be specified in terms of // pixel // values, and the default value is 0. // * The 'baseline' value is not supported for alignItems and alignSelf // properties. // * Values of width, maxWidth, minWidth, height, maxHeight and minHeight must // be // specified as pixel values, not as percentages. // * There is no support for calculation of dimensions based on intrinsic // aspect ratios // (e.g. images). // * There is no support for forced breaks. // * It does not support vertical inline directions (top-to-bottom or // bottom-to-top text). // // Deviations from standard: // * Section 4.5 of the spec indicates that all flex items have a default // minimum // main size. For text blocks, for example, this is the width of the widest // word. // Calculating the minimum width is expensive, so we forego it and assume a // default // minimum main size of 0. // * Min/Max sizes in the main axis are not honored when resolving flexible // lengths. // * The spec indicates that the default value for 'flexDirection' is 'row', // but // the algorithm below assumes a default of 'column'. // // Input parameters: // - node: current node to be sized and layed out // - availableWidth & availableHeight: available size to be used for sizing // the node // or YGUndefined if the size is not available; interpretation depends on // layout // flags // - parentDirection: the inline (text) direction within the parent // (left-to-right or // right-to-left) // - widthMeasureMode: indicates the sizing rules for the width (see below // for explanation) // - heightMeasureMode: indicates the sizing rules for the height (see below // for explanation) // - performLayout: specifies whether the caller is interested in just the // dimensions // of the node or it requires the entire node and its subtree to be layed // out // (with final positions) // // Details: // This routine is called recursively to lay out subtrees of flexbox // elements. It uses the // information in node.style, which is treated as a read-only input. It is // responsible for // setting the layout.direction and layout.measuredDimensions fields for the // input node as well // as the layout.position and layout.lineIndex fields for its child nodes. // The // layout.measuredDimensions field includes any border or padding for the // node but does // not include margins. // // The spec describes four different layout modes: "fill available", "max // content", "min // content", // and "fit content". Of these, we don't use "min content" because we don't // support default // minimum main sizes (see above for details). Each of our measure modes maps // to a layout mode // from the spec (https://www.w3.org/TR/YG3-sizing/#terms): // - YGMeasureModeUndefined: max content // - YGMeasureModeExactly: fill available // - YGMeasureModeAtMost: fit content // // When calling YGNodelayoutImpl and YGLayoutNodeInternal, if the caller passes // an available size of // undefined then it must also pass a measure mode of YGMeasureModeUndefined // in that dimension. // static void YGNodelayoutImpl(const YGNodeRef node, const float availableWidth, const float availableHeight, const YGDirection parentDirection, const YGMeasureMode widthMeasureMode, const YGMeasureMode heightMeasureMode, const bool performLayout) { YG_ASSERT(YGValueIsUndefined(availableWidth) ? widthMeasureMode == YGMeasureModeUndefined : true, "availableWidth is indefinite so widthMeasureMode must be " "YGMeasureModeUndefined"); YG_ASSERT(YGValueIsUndefined(availableHeight) ? heightMeasureMode == YGMeasureModeUndefined : true, "availableHeight is indefinite so heightMeasureMode must be " "YGMeasureModeUndefined"); // Set the resolved resolution in the node's layout. const YGDirection direction = YGNodeResolveDirection(node, parentDirection); node->layout.direction = direction; if (node->measure) { YGNodeWithMeasureFuncSetMeasuredDimensions( node, availableWidth, availableHeight, widthMeasureMode, heightMeasureMode); return; } const uint32_t childCount = YGNodeListCount(node->children); if (childCount == 0) { YGNodeEmptyContainerSetMeasuredDimensions( node, availableWidth, availableHeight, widthMeasureMode, heightMeasureMode); return; } // If we're not being asked to perform a full layout we can skip the algorithm if we already know // the size if (!performLayout && YGNodeFixedSizeSetMeasuredDimensions( node, availableWidth, availableHeight, widthMeasureMode, heightMeasureMode)) { return; } // STEP 1: CALCULATE VALUES FOR REMAINDER OF ALGORITHM const YGFlexDirection mainAxis = YGFlexDirectionResolve(node->style.flexDirection, direction); const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction); const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis); const YGJustify justifyContent = node->style.justifyContent; const bool isNodeFlexWrap = node->style.flexWrap == YGWrapWrap; YGNodeRef firstAbsoluteChild = NULL; YGNodeRef currentAbsoluteChild = NULL; const float leadingPaddingAndBorderMain = YGNodeLeadingPaddingAndBorder(node, mainAxis); const float trailingPaddingAndBorderMain = YGNodeTrailingPaddingAndBorder(node, mainAxis); const float leadingPaddingAndBorderCross = YGNodeLeadingPaddingAndBorder(node, crossAxis); const float paddingAndBorderAxisMain = YGNodePaddingAndBorderForAxis(node, mainAxis); const float paddingAndBorderAxisCross = YGNodePaddingAndBorderForAxis(node, crossAxis); const YGMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode; const YGMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode; const float paddingAndBorderAxisRow = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow); const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn); const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow); const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow; const float minInnerWidth = node->style.minDimensions[YGDimensionWidth] - marginAxisRow - paddingAndBorderAxisRow; const float maxInnerWidth = node->style.maxDimensions[YGDimensionWidth] - marginAxisRow - paddingAndBorderAxisRow; float availableInnerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn; const float minInnerHeight = node->style.minDimensions[YGDimensionHeight] - marginAxisColumn - paddingAndBorderAxisColumn; const float maxInnerHeight = node->style.maxDimensions[YGDimensionHeight] - marginAxisColumn - paddingAndBorderAxisColumn; const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight; const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight; // Max dimension overrides predefined dimension value; Min dimension in turn overrides both of the above if (!YGValueIsUndefined(availableInnerWidth)) { availableInnerWidth = fmaxf(fminf(availableInnerWidth, maxInnerWidth), minInnerWidth); } if (!YGValueIsUndefined(availableInnerHeight)) { availableInnerHeight = fmaxf(fminf(availableInnerHeight, maxInnerHeight), minInnerHeight); } float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight; const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth; // If there is only one child with flexGrow + flexShrink it means we can set the // computedFlexBasis to 0 instead of measuring and shrinking / flexing the child to exactly // match the remaining space YGNodeRef singleFlexChild = NULL; if ((isMainAxisRow && widthMeasureMode == YGMeasureModeExactly) || (!isMainAxisRow && heightMeasureMode == YGMeasureModeExactly)) { for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef child = YGNodeGetChild(node, i); if (singleFlexChild) { if (YGNodeIsFlex(child)) { // There is already a flexible child, abort. singleFlexChild = NULL; break; } } else if (YGNodeStyleGetFlexGrow(child) > 0 && YGNodeStyleGetFlexShrink(child) > 0) { singleFlexChild = child; } } } // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef child = YGNodeListGet(node->children, i); if (performLayout) { // Set the initial position (relative to the parent). const YGDirection childDirection = YGNodeResolveDirection(child, direction); YGNodeSetPosition(child, childDirection); } // Absolute-positioned children don't participate in flex layout. Add them // to a list that we can process later. if (child->style.positionType == YGPositionTypeAbsolute) { // Store a private linked list of absolutely positioned children // so that we can efficiently traverse them later. if (firstAbsoluteChild == NULL) { firstAbsoluteChild = child; } if (currentAbsoluteChild != NULL) { currentAbsoluteChild->nextChild = child; } currentAbsoluteChild = child; child->nextChild = NULL; } else { if (child == singleFlexChild) { child->layout.computedFlexBasisGeneration = gCurrentGenerationCount; child->layout.computedFlexBasis = 0; } else { YGNodeComputeFlexBasisForChild(node, child, availableInnerWidth, widthMeasureMode, availableInnerHeight, heightMeasureMode, direction); } } } // STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES // Indexes of children that represent the first and last items in the line. uint32_t startOfLineIndex = 0; uint32_t endOfLineIndex = 0; // Number of lines. uint32_t lineCount = 0; // Accumulated cross dimensions of all lines so far. float totalLineCrossDim = 0; // Max main dimension of all the lines. float maxLineMainDim = 0; for (; endOfLineIndex < childCount; lineCount++, startOfLineIndex = endOfLineIndex) { // Number of items on the currently line. May be different than the // difference // between start and end indicates because we skip over absolute-positioned // items. uint32_t itemsOnLine = 0; // sizeConsumedOnCurrentLine is accumulation of the dimensions and margin // of all the children on the current line. This will be used in order to // either set the dimensions of the node if none already exist or to compute // the remaining space left for the flexible children. float sizeConsumedOnCurrentLine = 0; float totalFlexGrowFactors = 0; float totalFlexShrinkScaledFactors = 0; // Maintain a linked list of the child nodes that can shrink and/or grow. YGNodeRef firstRelativeChild = NULL; YGNodeRef currentRelativeChild = NULL; // Add items to the current line until it's full or we run out of items. for (uint32_t i = startOfLineIndex; i < childCount; i++, endOfLineIndex++) { const YGNodeRef child = YGNodeListGet(node->children, i); child->lineIndex = lineCount; if (child->style.positionType != YGPositionTypeAbsolute) { const float outerFlexBasis = child->layout.computedFlexBasis + YGNodeMarginForAxis(child, mainAxis); // If this is a multi-line flow and this item pushes us over the // available size, we've // hit the end of the current line. Break out of the loop and lay out // the current line. if (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) { break; } sizeConsumedOnCurrentLine += outerFlexBasis; itemsOnLine++; if (YGNodeIsFlex(child)) { totalFlexGrowFactors += YGNodeStyleGetFlexGrow(child); // Unlike the grow factor, the shrink factor is scaled relative to the // child // dimension. totalFlexShrinkScaledFactors += -YGNodeStyleGetFlexShrink(child) * child->layout.computedFlexBasis; } // Store a private linked list of children that need to be layed out. if (firstRelativeChild == NULL) { firstRelativeChild = child; } if (currentRelativeChild != NULL) { currentRelativeChild->nextChild = child; } currentRelativeChild = child; child->nextChild = NULL; } } // If we don't need to measure the cross axis, we can skip the entire flex // step. const bool canSkipFlex = !performLayout && measureModeCrossDim == YGMeasureModeExactly; // In order to position the elements in the main axis, we have two // controls. The space between the beginning and the first element // and the space between each two elements. float leadingMainDim = 0; float betweenMainDim = 0; // STEP 5: RESOLVING FLEXIBLE LENGTHS ON MAIN AXIS // Calculate the remaining available space that needs to be allocated. // If the main dimension size isn't known, it is computed based on // the line length, so there's no more space left to distribute. // We resolve main dimension to fit minimum and maximum values if (YGValueIsUndefined(availableInnerMainDim)) { if (!YGValueIsUndefined(minInnerMainDim) && sizeConsumedOnCurrentLine < minInnerMainDim) { availableInnerMainDim = minInnerMainDim; } else if (!YGValueIsUndefined(maxInnerMainDim) && sizeConsumedOnCurrentLine > maxInnerMainDim) { availableInnerMainDim = maxInnerMainDim; } } float remainingFreeSpace = 0; if (!YGValueIsUndefined(availableInnerMainDim)) { remainingFreeSpace = availableInnerMainDim - sizeConsumedOnCurrentLine; } else if (sizeConsumedOnCurrentLine < 0) { // availableInnerMainDim is indefinite which means the node is being sized // based on its // content. // sizeConsumedOnCurrentLine is negative which means the node will // allocate 0 pixels for // its content. Consequently, remainingFreeSpace is 0 - // sizeConsumedOnCurrentLine. remainingFreeSpace = -sizeConsumedOnCurrentLine; } const float originalRemainingFreeSpace = remainingFreeSpace; float deltaFreeSpace = 0; if (!canSkipFlex) { float childFlexBasis; float flexShrinkScaledFactor; float flexGrowFactor; float baseMainSize; float boundMainSize; // Do two passes over the flex items to figure out how to distribute the // remaining space. // The first pass finds the items whose min/max constraints trigger, // freezes them at those // sizes, and excludes those sizes from the remaining space. The second // pass sets the size // of each flexible item. It distributes the remaining space amongst the // items whose min/max // constraints didn't trigger in pass 1. For the other items, it sets // their sizes by forcing // their min/max constraints to trigger again. // // This two pass approach for resolving min/max constraints deviates from // the spec. The // spec (https://www.w3.org/TR/YG-flexbox-1/#resolve-flexible-lengths) // describes a process // that needs to be repeated a variable number of times. The algorithm // implemented here // won't handle all cases but it was simpler to implement and it mitigates // performance // concerns because we know exactly how many passes it'll do. // First pass: detect the flex items whose min/max constraints trigger float deltaFlexShrinkScaledFactors = 0; float deltaFlexGrowFactors = 0; currentRelativeChild = firstRelativeChild; while (currentRelativeChild != NULL) { childFlexBasis = currentRelativeChild->layout.computedFlexBasis; if (remainingFreeSpace < 0) { flexShrinkScaledFactor = -YGNodeStyleGetFlexShrink(currentRelativeChild) * childFlexBasis; // Is this child able to shrink? if (flexShrinkScaledFactor != 0) { baseMainSize = childFlexBasis + remainingFreeSpace / totalFlexShrinkScaledFactors * flexShrinkScaledFactor; boundMainSize = YGNodeBoundAxis(currentRelativeChild, mainAxis, baseMainSize); if (baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, // this item's // min/max constraints should also trigger in the second pass // resulting in the // item's size calculation being identical in the first and second // passes. deltaFreeSpace -= boundMainSize - childFlexBasis; deltaFlexShrinkScaledFactors -= flexShrinkScaledFactor; } } } else if (remainingFreeSpace > 0) { flexGrowFactor = YGNodeStyleGetFlexGrow(currentRelativeChild); // Is this child able to grow? if (flexGrowFactor != 0) { baseMainSize = childFlexBasis + remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor; boundMainSize = YGNodeBoundAxis(currentRelativeChild, mainAxis, baseMainSize); if (baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, // this item's // min/max constraints should also trigger in the second pass // resulting in the // item's size calculation being identical in the first and second // passes. deltaFreeSpace -= boundMainSize - childFlexBasis; deltaFlexGrowFactors -= flexGrowFactor; } } } currentRelativeChild = currentRelativeChild->nextChild; } totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors; totalFlexGrowFactors += deltaFlexGrowFactors; remainingFreeSpace += deltaFreeSpace; // Second pass: resolve the sizes of the flexible items deltaFreeSpace = 0; currentRelativeChild = firstRelativeChild; while (currentRelativeChild != NULL) { childFlexBasis = currentRelativeChild->layout.computedFlexBasis; float updatedMainSize = childFlexBasis; if (remainingFreeSpace < 0) { flexShrinkScaledFactor = -YGNodeStyleGetFlexShrink(currentRelativeChild) * childFlexBasis; // Is this child able to shrink? if (flexShrinkScaledFactor != 0) { float childSize; if (totalFlexShrinkScaledFactors == 0) { childSize = childFlexBasis + flexShrinkScaledFactor; } else { childSize = childFlexBasis + (remainingFreeSpace / totalFlexShrinkScaledFactors) * flexShrinkScaledFactor; } updatedMainSize = YGNodeBoundAxis(currentRelativeChild, mainAxis, childSize); } } else if (remainingFreeSpace > 0) { flexGrowFactor = YGNodeStyleGetFlexGrow(currentRelativeChild); // Is this child able to grow? if (flexGrowFactor != 0) { updatedMainSize = YGNodeBoundAxis(currentRelativeChild, mainAxis, childFlexBasis + remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor); } } deltaFreeSpace -= updatedMainSize - childFlexBasis; float childWidth; float childHeight; YGMeasureMode childWidthMeasureMode; YGMeasureMode childHeightMeasureMode; if (isMainAxisRow) { childWidth = updatedMainSize + YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionRow); childWidthMeasureMode = YGMeasureModeExactly; if (!YGValueIsUndefined(availableInnerCrossDim) && !YGNodeIsStyleDimDefined(currentRelativeChild, YGFlexDirectionColumn) && heightMeasureMode == YGMeasureModeExactly && YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch) { childHeight = availableInnerCrossDim; childHeightMeasureMode = YGMeasureModeExactly; } else if (!YGNodeIsStyleDimDefined(currentRelativeChild, YGFlexDirectionColumn)) { childHeight = availableInnerCrossDim; childHeightMeasureMode = YGValueIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeAtMost; } else { childHeight = currentRelativeChild->style.dimensions[YGDimensionHeight] + YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionColumn); childHeightMeasureMode = YGMeasureModeExactly; } } else { childHeight = updatedMainSize + YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionColumn); childHeightMeasureMode = YGMeasureModeExactly; if (!YGValueIsUndefined(availableInnerCrossDim) && !YGNodeIsStyleDimDefined(currentRelativeChild, YGFlexDirectionRow) && widthMeasureMode == YGMeasureModeExactly && YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch) { childWidth = availableInnerCrossDim; childWidthMeasureMode = YGMeasureModeExactly; } else if (!YGNodeIsStyleDimDefined(currentRelativeChild, YGFlexDirectionRow)) { childWidth = availableInnerCrossDim; childWidthMeasureMode = YGValueIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeAtMost; } else { childWidth = currentRelativeChild->style.dimensions[YGDimensionWidth] + YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionRow); childWidthMeasureMode = YGMeasureModeExactly; } } if (!YGValueIsUndefined(currentRelativeChild->style.aspectRatio)) { if (isMainAxisRow && childHeightMeasureMode != YGMeasureModeExactly) { childHeight = fmaxf(childWidth * currentRelativeChild->style.aspectRatio, YGNodePaddingAndBorderForAxis(currentRelativeChild, YGFlexDirectionColumn)); childHeightMeasureMode = YGMeasureModeExactly; } else if (!isMainAxisRow && childWidthMeasureMode != YGMeasureModeExactly) { childWidth = fmaxf(childHeight * currentRelativeChild->style.aspectRatio, YGNodePaddingAndBorderForAxis(currentRelativeChild, YGFlexDirectionRow)); childWidthMeasureMode = YGMeasureModeExactly; } } YGConstrainMaxSizeForMode(currentRelativeChild->style.maxDimensions[YGDimensionWidth], &childWidthMeasureMode, &childWidth); YGConstrainMaxSizeForMode(currentRelativeChild->style.maxDimensions[YGDimensionHeight], &childHeightMeasureMode, &childHeight); const bool requiresStretchLayout = !YGNodeIsStyleDimDefined(currentRelativeChild, crossAxis) && YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch; // Recursively call the layout algorithm for this child with the updated // main size. YGLayoutNodeInternal(currentRelativeChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, performLayout && !requiresStretchLayout, "flex"); currentRelativeChild = currentRelativeChild->nextChild; } } remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace; // STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION // At this point, all the children have their dimensions set in the main // axis. // Their dimensions are also set in the cross axis with the exception of // items // that are aligned "stretch". We need to compute these stretch values and // set the final positions. // If we are using "at most" rules in the main axis. Calculate the remaining space when // constraint by the min size defined for the main axis. if (measureModeMainDim == YGMeasureModeAtMost && remainingFreeSpace > 0) { if (!YGValueIsUndefined(node->style.minDimensions[dim[mainAxis]]) && node->style.minDimensions[dim[mainAxis]] >= 0) { remainingFreeSpace = fmaxf(0, node->style.minDimensions[dim[mainAxis]] - (availableInnerMainDim - remainingFreeSpace)); } else { remainingFreeSpace = 0; } } switch (justifyContent) { case YGJustifyCenter: leadingMainDim = remainingFreeSpace / 2; break; case YGJustifyFlexEnd: leadingMainDim = remainingFreeSpace; break; case YGJustifySpaceBetween: if (itemsOnLine > 1) { betweenMainDim = fmaxf(remainingFreeSpace, 0) / (itemsOnLine - 1); } else { betweenMainDim = 0; } break; case YGJustifySpaceAround: // Space on the edges is half of the space between elements betweenMainDim = remainingFreeSpace / itemsOnLine; leadingMainDim = betweenMainDim / 2; break; case YGJustifyFlexStart: case YGJustifyCount: break; } float mainDim = leadingPaddingAndBorderMain + leadingMainDim; float crossDim = 0; for (uint32_t i = startOfLineIndex; i < endOfLineIndex; i++) { const YGNodeRef child = YGNodeListGet(node->children, i); if (child->style.positionType == YGPositionTypeAbsolute && YGNodeIsLeadingPosDefined(child, mainAxis)) { if (performLayout) { // In case the child is position absolute and has left/top being // defined, we override the position to whatever the user said // (and margin/border). child->layout.position[pos[mainAxis]] = YGNodeLeadingPosition(child, mainAxis) + YGNodeLeadingBorder(node, mainAxis) + YGNodeLeadingMargin(child, mainAxis); } } else { // Now that we placed the element, we need to update the variables. // We need to do that only for relative elements. Absolute elements // do not take part in that phase. if (child->style.positionType == YGPositionTypeRelative) { if (performLayout) { child->layout.position[pos[mainAxis]] += mainDim; } if (canSkipFlex) { // If we skipped the flex step, then we can't rely on the // measuredDims because // they weren't computed. This means we can't call YGNodeDimWithMargin. mainDim += betweenMainDim + YGNodeMarginForAxis(child, mainAxis) + child->layout.computedFlexBasis; crossDim = availableInnerCrossDim; } else { // The main dimension is the sum of all the elements dimension plus // the spacing. mainDim += betweenMainDim + YGNodeDimWithMargin(child, mainAxis); // The cross dimension is the max of the elements dimension since // there // can only be one element in that cross dimension. crossDim = fmaxf(crossDim, YGNodeDimWithMargin(child, crossAxis)); } } else if (performLayout) { child->layout.position[pos[mainAxis]] += YGNodeLeadingBorder(node, mainAxis) + leadingMainDim; } } } mainDim += trailingPaddingAndBorderMain; float containerCrossAxis = availableInnerCrossDim; if (measureModeCrossDim == YGMeasureModeUndefined || measureModeCrossDim == YGMeasureModeAtMost) { // Compute the cross axis from the max cross dimension of the children. containerCrossAxis = YGNodeBoundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross; if (measureModeCrossDim == YGMeasureModeAtMost) { containerCrossAxis = fminf(containerCrossAxis, availableInnerCrossDim); } } // If there's no flex wrap, the cross dimension is defined by the container. if (!isNodeFlexWrap && measureModeCrossDim == YGMeasureModeExactly) { crossDim = availableInnerCrossDim; } // Clamp to the min/max size specified on the container. crossDim = YGNodeBoundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross; // STEP 7: CROSS-AXIS ALIGNMENT // We can skip child alignment if we're just measuring the container. if (performLayout) { for (uint32_t i = startOfLineIndex; i < endOfLineIndex; i++) { const YGNodeRef child = YGNodeListGet(node->children, i); if (child->style.positionType == YGPositionTypeAbsolute) { // If the child is absolutely positioned and has a // top/left/bottom/right // set, override all the previously computed positions to set it // correctly. if (YGNodeIsLeadingPosDefined(child, crossAxis)) { child->layout.position[pos[crossAxis]] = YGNodeLeadingPosition(child, crossAxis) + YGNodeLeadingBorder(node, crossAxis) + YGNodeLeadingMargin(child, crossAxis); } else { child->layout.position[pos[crossAxis]] = YGNodeLeadingBorder(node, crossAxis) + YGNodeLeadingMargin(child, crossAxis); } } else { float leadingCrossDim = leadingPaddingAndBorderCross; // For a relative children, we're either using alignItems (parent) or // alignSelf (child) in order to determine the position in the cross // axis const YGAlign alignItem = YGNodeAlignItem(node, child); // If the child uses align stretch, we need to lay it out one more // time, this time // forcing the cross-axis size to be the computed cross size for the // current line. if (alignItem == YGAlignStretch) { const bool isCrossSizeDefinite = (isMainAxisRow && YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn)) || (!isMainAxisRow && YGNodeIsStyleDimDefined(child, YGFlexDirectionRow)); float childWidth; float childHeight; YGMeasureMode childWidthMeasureMode = YGMeasureModeExactly; YGMeasureMode childHeightMeasureMode = YGMeasureModeExactly; if (isMainAxisRow) { childHeight = crossDim; childWidth = child->layout.measuredDimensions[YGDimensionWidth] + YGNodeMarginForAxis(child, YGFlexDirectionRow); } else { childWidth = crossDim; childHeight = child->layout.measuredDimensions[YGDimensionHeight] + YGNodeMarginForAxis(child, YGFlexDirectionColumn); } YGConstrainMaxSizeForMode(child->style.maxDimensions[YGDimensionWidth], &childWidthMeasureMode, &childWidth); YGConstrainMaxSizeForMode(child->style.maxDimensions[YGDimensionHeight], &childHeightMeasureMode, &childHeight); // If the child defines a definite size for its cross axis, there's // no need to stretch. if (!isCrossSizeDefinite) { childWidthMeasureMode = YGValueIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly; childHeightMeasureMode = YGValueIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly; YGLayoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, true, "stretch"); } } else if (alignItem != YGAlignFlexStart) { const float remainingCrossDim = containerCrossAxis - YGNodeDimWithMargin(child, crossAxis); if (alignItem == YGAlignCenter) { leadingCrossDim += remainingCrossDim / 2; } else { // YGAlignFlexEnd leadingCrossDim += remainingCrossDim; } } // And we apply the position child->layout.position[pos[crossAxis]] += totalLineCrossDim + leadingCrossDim; } } } totalLineCrossDim += crossDim; maxLineMainDim = fmaxf(maxLineMainDim, mainDim); } // STEP 8: MULTI-LINE CONTENT ALIGNMENT if (lineCount > 1 && performLayout && !YGValueIsUndefined(availableInnerCrossDim)) { const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim; float crossDimLead = 0; float currentLead = leadingPaddingAndBorderCross; switch (node->style.alignContent) { case YGAlignFlexEnd: currentLead += remainingAlignContentDim; break; case YGAlignCenter: currentLead += remainingAlignContentDim / 2; break; case YGAlignStretch: if (availableInnerCrossDim > totalLineCrossDim) { crossDimLead = (remainingAlignContentDim / lineCount); } break; case YGAlignAuto: case YGAlignFlexStart: case YGAlignCount: break; } uint32_t endIndex = 0; for (uint32_t i = 0; i < lineCount; i++) { uint32_t startIndex = endIndex; uint32_t ii; // compute the line's height and find the endIndex float lineHeight = 0; for (ii = startIndex; ii < childCount; ii++) { const YGNodeRef child = YGNodeListGet(node->children, ii); if (child->style.positionType == YGPositionTypeRelative) { if (child->lineIndex != i) { break; } if (YGNodeIsLayoutDimDefined(child, crossAxis)) { lineHeight = fmaxf(lineHeight, child->layout.measuredDimensions[dim[crossAxis]] + YGNodeMarginForAxis(child, crossAxis)); } } } endIndex = ii; lineHeight += crossDimLead; if (performLayout) { for (ii = startIndex; ii < endIndex; ii++) { const YGNodeRef child = YGNodeListGet(node->children, ii); if (child->style.positionType == YGPositionTypeRelative) { switch (YGNodeAlignItem(node, child)) { case YGAlignFlexStart: { child->layout.position[pos[crossAxis]] = currentLead + YGNodeLeadingMargin(child, crossAxis); break; } case YGAlignFlexEnd: { child->layout.position[pos[crossAxis]] = currentLead + lineHeight - YGNodeTrailingMargin(child, crossAxis) - child->layout.measuredDimensions[dim[crossAxis]]; break; } case YGAlignCenter: { float childHeight = child->layout.measuredDimensions[dim[crossAxis]]; child->layout.position[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2; break; } case YGAlignStretch: { child->layout.position[pos[crossAxis]] = currentLead + YGNodeLeadingMargin(child, crossAxis); // TODO(prenaux): Correctly set the height of items with indefinite // (auto) crossAxis dimension. break; } case YGAlignAuto: case YGAlignCount: break; } } } } currentLead += lineHeight; } } // STEP 9: COMPUTING FINAL DIMENSIONS node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis(node, YGFlexDirectionRow, availableWidth - marginAxisRow); node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(node, YGFlexDirectionColumn, availableHeight - marginAxisColumn); // If the user didn't specify a width or height for the node, set the // dimensions based on the children. if (measureModeMainDim == YGMeasureModeUndefined) { // Clamp the size to the min/max size, if specified, and make sure it // doesn't go below the padding and border amount. node->layout.measuredDimensions[dim[mainAxis]] = YGNodeBoundAxis(node, mainAxis, maxLineMainDim); } else if (measureModeMainDim == YGMeasureModeAtMost) { node->layout.measuredDimensions[dim[mainAxis]] = fmaxf(fminf(availableInnerMainDim + paddingAndBorderAxisMain, YGNodeBoundAxisWithinMinAndMax(node, mainAxis, maxLineMainDim)), paddingAndBorderAxisMain); } if (measureModeCrossDim == YGMeasureModeUndefined) { // Clamp the size to the min/max size, if specified, and make sure it // doesn't go below the padding and border amount. node->layout.measuredDimensions[dim[crossAxis]] = YGNodeBoundAxis(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross); } else if (measureModeCrossDim == YGMeasureModeAtMost) { node->layout.measuredDimensions[dim[crossAxis]] = fmaxf(fminf(availableInnerCrossDim + paddingAndBorderAxisCross, YGNodeBoundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)), paddingAndBorderAxisCross); } if (performLayout) { // STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN for (currentAbsoluteChild = firstAbsoluteChild; currentAbsoluteChild != NULL; currentAbsoluteChild = currentAbsoluteChild->nextChild) { YGNodeAbsoluteLayoutChild( node, currentAbsoluteChild, availableInnerWidth, widthMeasureMode, direction); } // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN const bool needsMainTrailingPos = mainAxis == YGFlexDirectionRowReverse || mainAxis == YGFlexDirectionColumnReverse; const bool needsCrossTrailingPos = crossAxis == YGFlexDirectionRowReverse || crossAxis == YGFlexDirectionColumnReverse; // Set trailing position if necessary. if (needsMainTrailingPos || needsCrossTrailingPos) { for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef child = YGNodeListGet(node->children, i); if (needsMainTrailingPos) { YGNodeSetChildTrailingPosition(node, child, mainAxis); } if (needsCrossTrailingPos) { YGNodeSetChildTrailingPosition(node, child, crossAxis); } } } } } uint32_t gDepth = 0; bool gPrintTree = false; bool gPrintChanges = false; bool gPrintSkips = false; static const char *spacer = " "; static const char *YGSpacer(const unsigned long level) { const size_t spacerLen = strlen(spacer); if (level > spacerLen) { return &spacer[0]; } else { return &spacer[spacerLen - level]; } } static const char *YGMeasureModeName(const YGMeasureMode mode, const bool performLayout) { const char *kMeasureModeNames[YGMeasureModeCount] = {"UNDEFINED", "EXACTLY", "AT_MOST"}; const char *kLayoutModeNames[YGMeasureModeCount] = {"LAY_UNDEFINED", "LAY_EXACTLY", "LAY_AT_" "MOST"}; if (mode >= YGMeasureModeCount) { return ""; } return performLayout ? kLayoutModeNames[mode] : kMeasureModeNames[mode]; } static inline bool YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(YGMeasureMode sizeMode, float size, float lastComputedSize) { return sizeMode == YGMeasureModeExactly && YGFloatsEqual(size, lastComputedSize); } static inline bool YGMeasureModeOldSizeIsUnspecifiedAndStillFits(YGMeasureMode sizeMode, float size, YGMeasureMode lastSizeMode, float lastComputedSize) { return sizeMode == YGMeasureModeAtMost && lastSizeMode == YGMeasureModeUndefined && size >= lastComputedSize; } static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(YGMeasureMode sizeMode, float size, YGMeasureMode lastSizeMode, float lastSize, float lastComputedSize) { return lastSizeMode == YGMeasureModeAtMost && sizeMode == YGMeasureModeAtMost && lastSize > size && lastComputedSize <= size; } bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode, const float width, const YGMeasureMode heightMode, const float height, const YGMeasureMode lastWidthMode, const float lastWidth, const YGMeasureMode lastHeightMode, const float lastHeight, const float lastComputedWidth, const float lastComputedHeight, const float marginRow, const float marginColumn) { if (lastComputedHeight < 0 || lastComputedWidth < 0) { return false; } const bool hasSameWidthSpec = lastWidthMode == widthMode && YGFloatsEqual(lastWidth, width); const bool hasSameHeightSpec = lastHeightMode == heightMode && YGFloatsEqual(lastHeight, height); const bool widthIsCompatible = hasSameWidthSpec || YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(widthMode, width - marginRow, lastComputedWidth) || YGMeasureModeOldSizeIsUnspecifiedAndStillFits(widthMode, width - marginRow, lastWidthMode, lastComputedWidth) || YGMeasureModeNewMeasureSizeIsStricterAndStillValid( widthMode, width - marginRow, lastWidthMode, lastWidth, lastComputedWidth); const bool heightIsCompatible = hasSameHeightSpec || YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(heightMode, height - marginColumn, lastComputedHeight) || YGMeasureModeOldSizeIsUnspecifiedAndStillFits(heightMode, height - marginColumn, lastHeightMode, lastComputedHeight) || YGMeasureModeNewMeasureSizeIsStricterAndStillValid( heightMode, height - marginColumn, lastHeightMode, lastHeight, lastComputedHeight); return widthIsCompatible && heightIsCompatible; } // // This is a wrapper around the YGNodelayoutImpl function. It determines // whether the layout request is redundant and can be skipped. // // Parameters: // Input parameters are the same as YGNodelayoutImpl (see above) // Return parameter is true if layout was performed, false if skipped // bool YGLayoutNodeInternal(const YGNodeRef node, const float availableWidth, const float availableHeight, const YGDirection parentDirection, const YGMeasureMode widthMeasureMode, const YGMeasureMode heightMeasureMode, const bool performLayout, const char *reason) { YGLayout *layout = &node->layout; gDepth++; const bool needToVisitNode = (node->isDirty && layout->generationCount != gCurrentGenerationCount) || layout->lastParentDirection != parentDirection; if (needToVisitNode) { // Invalidate the cached results. layout->nextCachedMeasurementsIndex = 0; layout->cachedLayout.widthMeasureMode = (YGMeasureMode) -1; layout->cachedLayout.heightMeasureMode = (YGMeasureMode) -1; layout->cachedLayout.computedWidth = -1; layout->cachedLayout.computedHeight = -1; } YGCachedMeasurement *cachedResults = NULL; // Determine whether the results are already cached. We maintain a separate // cache for layouts and measurements. A layout operation modifies the // positions // and dimensions for nodes in the subtree. The algorithm assumes that each // node // gets layed out a maximum of one time per tree layout, but multiple // measurements // may be required to resolve all of the flex dimensions. // We handle nodes with measure functions specially here because they are the // most // expensive to measure, so it's worth avoiding redundant measurements if at // all possible. if (node->measure) { const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow); const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); // First, try to use the layout cache. if (YGNodeCanUseCachedMeasurement(widthMeasureMode, availableWidth, heightMeasureMode, availableHeight, layout->cachedLayout.widthMeasureMode, layout->cachedLayout.availableWidth, layout->cachedLayout.heightMeasureMode, layout->cachedLayout.availableHeight, layout->cachedLayout.computedWidth, layout->cachedLayout.computedHeight, marginAxisRow, marginAxisColumn)) { cachedResults = &layout->cachedLayout; } else { // Try to use the measurement cache. for (uint32_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) { if (YGNodeCanUseCachedMeasurement(widthMeasureMode, availableWidth, heightMeasureMode, availableHeight, layout->cachedMeasurements[i].widthMeasureMode, layout->cachedMeasurements[i].availableWidth, layout->cachedMeasurements[i].heightMeasureMode, layout->cachedMeasurements[i].availableHeight, layout->cachedMeasurements[i].computedWidth, layout->cachedMeasurements[i].computedHeight, marginAxisRow, marginAxisColumn)) { cachedResults = &layout->cachedMeasurements[i]; break; } } } } else if (performLayout) { if (YGFloatsEqual(layout->cachedLayout.availableWidth, availableWidth) && YGFloatsEqual(layout->cachedLayout.availableHeight, availableHeight) && layout->cachedLayout.widthMeasureMode == widthMeasureMode && layout->cachedLayout.heightMeasureMode == heightMeasureMode) { cachedResults = &layout->cachedLayout; } } else { for (uint32_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) { if (YGFloatsEqual(layout->cachedMeasurements[i].availableWidth, availableWidth) && YGFloatsEqual(layout->cachedMeasurements[i].availableHeight, availableHeight) && layout->cachedMeasurements[i].widthMeasureMode == widthMeasureMode && layout->cachedMeasurements[i].heightMeasureMode == heightMeasureMode) { cachedResults = &layout->cachedMeasurements[i]; break; } } } if (!needToVisitNode && cachedResults != NULL) { layout->measuredDimensions[YGDimensionWidth] = cachedResults->computedWidth; layout->measuredDimensions[YGDimensionHeight] = cachedResults->computedHeight; if (gPrintChanges && gPrintSkips) { printf("%s%d.{[skipped] ", YGSpacer(gDepth), gDepth); if (node->print) { node->print(node); } printf("wm: %s, hm: %s, aw: %f ah: %f => d: (%f, %f) %s\n", YGMeasureModeName(widthMeasureMode, performLayout), YGMeasureModeName(heightMeasureMode, performLayout), availableWidth, availableHeight, cachedResults->computedWidth, cachedResults->computedHeight, reason); } } else { if (gPrintChanges) { printf("%s%d.{%s", YGSpacer(gDepth), gDepth, needToVisitNode ? "*" : ""); if (node->print) { node->print(node); } printf("wm: %s, hm: %s, aw: %f ah: %f %s\n", YGMeasureModeName(widthMeasureMode, performLayout), YGMeasureModeName(heightMeasureMode, performLayout), availableWidth, availableHeight, reason); } YGNodelayoutImpl(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, performLayout); if (gPrintChanges) { printf("%s%d.}%s", YGSpacer(gDepth), gDepth, needToVisitNode ? "*" : ""); if (node->print) { node->print(node); } printf("wm: %s, hm: %s, d: (%f, %f) %s\n", YGMeasureModeName(widthMeasureMode, performLayout), YGMeasureModeName(heightMeasureMode, performLayout), layout->measuredDimensions[YGDimensionWidth], layout->measuredDimensions[YGDimensionHeight], reason); } layout->lastParentDirection = parentDirection; if (cachedResults == NULL) { if (layout->nextCachedMeasurementsIndex == YG_MAX_CACHED_RESULT_COUNT) { if (gPrintChanges) { printf("Out of cache entries!\n"); } layout->nextCachedMeasurementsIndex = 0; } YGCachedMeasurement *newCacheEntry; if (performLayout) { // Use the single layout cache entry. newCacheEntry = &layout->cachedLayout; } else { // Allocate a new measurement cache entry. newCacheEntry = &layout->cachedMeasurements[layout->nextCachedMeasurementsIndex]; layout->nextCachedMeasurementsIndex++; } newCacheEntry->availableWidth = availableWidth; newCacheEntry->availableHeight = availableHeight; newCacheEntry->widthMeasureMode = widthMeasureMode; newCacheEntry->heightMeasureMode = heightMeasureMode; newCacheEntry->computedWidth = layout->measuredDimensions[YGDimensionWidth]; newCacheEntry->computedHeight = layout->measuredDimensions[YGDimensionHeight]; } } if (performLayout) { node->layout.dimensions[YGDimensionWidth] = node->layout.measuredDimensions[YGDimensionWidth]; node->layout.dimensions[YGDimensionHeight] = node->layout.measuredDimensions[YGDimensionHeight]; node->hasNewLayout = true; node->isDirty = false; } gDepth--; layout->generationCount = gCurrentGenerationCount; return (needToVisitNode || cachedResults == NULL); } static void roundToPixelGrid(const YGNodeRef node) { const float fractialLeft = node->layout.position[YGEdgeLeft] - floorf(node->layout.position[YGEdgeLeft]); const float fractialTop = node->layout.position[YGEdgeTop] - floorf(node->layout.position[YGEdgeTop]); node->layout.dimensions[YGDimensionWidth] = roundf(fractialLeft + node->layout.dimensions[YGDimensionWidth]) - roundf(fractialLeft); node->layout.dimensions[YGDimensionHeight] = roundf(fractialTop + node->layout.dimensions[YGDimensionHeight]) - roundf(fractialTop); node->layout.position[YGEdgeLeft] = roundf(node->layout.position[YGEdgeLeft]); node->layout.position[YGEdgeTop] = roundf(node->layout.position[YGEdgeTop]); const uint32_t childCount = YGNodeListCount(node->children); for (uint32_t i = 0; i < childCount; i++) { roundToPixelGrid(YGNodeGetChild(node, i)); } } void YGNodeCalculateLayout(const YGNodeRef node, const float availableWidth, const float availableHeight, const YGDirection parentDirection) { // Increment the generation count. This will force the recursive routine to // visit // all dirty nodes at least once. Subsequent visits will be skipped if the // input // parameters don't change. gCurrentGenerationCount++; float width = availableWidth; float height = availableHeight; YGMeasureMode widthMeasureMode = YGMeasureModeUndefined; YGMeasureMode heightMeasureMode = YGMeasureModeUndefined; if (!YGValueIsUndefined(width)) { widthMeasureMode = YGMeasureModeExactly; } else if (YGNodeIsStyleDimDefined(node, YGFlexDirectionRow)) { width = node->style.dimensions[dim[YGFlexDirectionRow]] + YGNodeMarginForAxis(node, YGFlexDirectionRow); widthMeasureMode = YGMeasureModeExactly; } else if (node->style.maxDimensions[YGDimensionWidth] >= 0.0) { width = node->style.maxDimensions[YGDimensionWidth]; widthMeasureMode = YGMeasureModeAtMost; } if (!YGValueIsUndefined(height)) { heightMeasureMode = YGMeasureModeExactly; } else if (YGNodeIsStyleDimDefined(node, YGFlexDirectionColumn)) { height = node->style.dimensions[dim[YGFlexDirectionColumn]] + YGNodeMarginForAxis(node, YGFlexDirectionColumn); heightMeasureMode = YGMeasureModeExactly; } else if (node->style.maxDimensions[YGDimensionHeight] >= 0.0) { height = node->style.maxDimensions[YGDimensionHeight]; heightMeasureMode = YGMeasureModeAtMost; } if (YGLayoutNodeInternal(node, width, height, parentDirection, widthMeasureMode, heightMeasureMode, true, "initia" "l")) { YGNodeSetPosition(node, node->layout.direction); if (YGIsExperimentalFeatureEnabled(YGExperimentalFeatureRounding)) { roundToPixelGrid(node); } if (gPrintTree) { YGNodePrint(node, YGPrintOptionsLayout | YGPrintOptionsChildren | YGPrintOptionsStyle); } } } void YGSetLogger(YGLogger logger) { gLogger = logger; } void YGLog(YGLogLevel level, const char *format, ...) { va_list args; va_start(args, format); gLogger(level, format, args); va_end(args); } static bool experimentalFeatures[YGExperimentalFeatureCount + 1]; void YGSetExperimentalFeatureEnabled(YGExperimentalFeature feature, bool enabled) { experimentalFeatures[feature] = enabled; } inline bool YGIsExperimentalFeatureEnabled(YGExperimentalFeature feature) { return experimentalFeatures[feature]; } void YGSetMemoryFuncs(YGMalloc ygmalloc, YGCalloc yccalloc, YGRealloc ygrealloc, YGFree ygfree) { YG_ASSERT(gNodeInstanceCount == 0, "Cannot set memory functions: all node must be freed first"); YG_ASSERT((ygmalloc == NULL && yccalloc == NULL && ygrealloc == NULL && ygfree == NULL) || (ygmalloc != NULL && yccalloc != NULL && ygrealloc != NULL && ygfree != NULL), "Cannot set memory functions: functions must be all NULL or Non-NULL"); if (ygmalloc == NULL || yccalloc == NULL || ygrealloc == NULL || ygfree == NULL) { gYGMalloc = &malloc; gYGCalloc = &calloc; gYGRealloc = &realloc; gYGFree = &free; } else { gYGMalloc = ygmalloc; gYGCalloc = yccalloc; gYGRealloc = ygrealloc; gYGFree = ygfree; } } ================================================ FILE: FlexBoxLayout/Classes/Layout/Yoga.h ================================================ /** * 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. */ #pragma once #include #include #include #include #include #include #ifndef __cplusplus #include #endif // Not defined in MSVC++ #ifndef NAN static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff}; #define NAN (*(const float *) __nan) #endif #define YGUndefined NAN #include "YGEnums.h" #include "YGMacros.h" YG_EXTERN_C_BEGIN typedef struct YGSize { float width; float height; } YGSize; typedef struct YGNode *YGNodeRef; typedef YGSize (*YGMeasureFunc)(YGNodeRef node, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode); typedef void (*YGPrintFunc)(YGNodeRef node); typedef int (*YGLogger)(YGLogLevel level, const char *format, va_list args); typedef void *(*YGMalloc)(size_t size); typedef void *(*YGCalloc)(size_t count, size_t size); typedef void *(*YGRealloc)(void *ptr, size_t size); typedef void (*YGFree)(void *ptr); // YGNode WIN_EXPORT YGNodeRef YGNodeNew(void); WIN_EXPORT void YGNodeFree(const YGNodeRef node); WIN_EXPORT void YGNodeFreeRecursive(const YGNodeRef node); WIN_EXPORT void YGNodeReset(const YGNodeRef node); WIN_EXPORT int32_t YGNodeGetInstanceCount(void); WIN_EXPORT void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index); WIN_EXPORT void YGNodeRemoveChild(const YGNodeRef node, const YGNodeRef child); WIN_EXPORT YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index); WIN_EXPORT YGNodeRef YGNodeGetParent(const YGNodeRef node); WIN_EXPORT uint32_t YGNodeGetChildCount(const YGNodeRef node); WIN_EXPORT void YGNodeCalculateLayout(const YGNodeRef node, const float availableWidth, const float availableHeight, const YGDirection parentDirection); // Mark a node as dirty. Only valid for nodes with a custom measure function // set. // YG knows when to mark all other nodes as dirty but because nodes with // measure functions // depends on information not known to YG they must perform this dirty // marking manually. WIN_EXPORT void YGNodeMarkDirty(const YGNodeRef node); WIN_EXPORT bool YGNodeIsDirty(const YGNodeRef node); WIN_EXPORT void YGNodePrint(const YGNodeRef node, const YGPrintOptions options); WIN_EXPORT bool YGValueIsUndefined(const float value); WIN_EXPORT bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode, const float width, const YGMeasureMode heightMode, const float height, const YGMeasureMode lastWidthMode, const float lastWidth, const YGMeasureMode lastHeightMode, const float lastHeight, const float lastComputedWidth, const float lastComputedHeight, const float marginRow, const float marginColumn); WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode); #define YG_NODE_PROPERTY(type, name, paramName) \ WIN_EXPORT void YGNodeSet##name(const YGNodeRef node, type paramName); \ WIN_EXPORT type YGNodeGet##name(const YGNodeRef node); #define YG_NODE_STYLE_PROPERTY(type, name, paramName) \ WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, const type paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); #define YG_NODE_STYLE_EDGE_PROPERTY(type, name, paramName) \ WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, \ const YGEdge edge, \ const type paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); #define YG_NODE_LAYOUT_PROPERTY(type, name) \ WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node); YG_NODE_PROPERTY(void *, Context, context); YG_NODE_PROPERTY(YGMeasureFunc, MeasureFunc, measureFunc); YG_NODE_PROPERTY(YGPrintFunc, PrintFunc, printFunc); YG_NODE_PROPERTY(bool, HasNewLayout, hasNewLayout); YG_NODE_STYLE_PROPERTY(YGDirection, Direction, direction); YG_NODE_STYLE_PROPERTY(YGFlexDirection, FlexDirection, flexDirection); YG_NODE_STYLE_PROPERTY(YGJustify, JustifyContent, justifyContent); YG_NODE_STYLE_PROPERTY(YGAlign, AlignContent, alignContent); YG_NODE_STYLE_PROPERTY(YGAlign, AlignItems, alignItems); YG_NODE_STYLE_PROPERTY(YGAlign, AlignSelf, alignSelf); YG_NODE_STYLE_PROPERTY(YGPositionType, PositionType, positionType); YG_NODE_STYLE_PROPERTY(YGWrap, FlexWrap, flexWrap); YG_NODE_STYLE_PROPERTY(YGOverflow, Overflow, overflow); WIN_EXPORT void YGNodeStyleSetFlex(const YGNodeRef node, const float flex); YG_NODE_STYLE_PROPERTY(float, FlexGrow, flexGrow); YG_NODE_STYLE_PROPERTY(float, FlexShrink, flexShrink); YG_NODE_STYLE_PROPERTY(float, FlexBasis, flexBasis); YG_NODE_STYLE_EDGE_PROPERTY(float, Position, position); YG_NODE_STYLE_EDGE_PROPERTY(float, Margin, margin); YG_NODE_STYLE_EDGE_PROPERTY(float, Padding, padding); YG_NODE_STYLE_EDGE_PROPERTY(float, Border, border); YG_NODE_STYLE_PROPERTY(float, Width, width); YG_NODE_STYLE_PROPERTY(float, Height, height); YG_NODE_STYLE_PROPERTY(float, MinWidth, minWidth); YG_NODE_STYLE_PROPERTY(float, MinHeight, minHeight); YG_NODE_STYLE_PROPERTY(float, MaxWidth, maxWidth); YG_NODE_STYLE_PROPERTY(float, MaxHeight, maxHeight); // Yoga specific properties, not compatible with flexbox specification // Aspect ratio control the size of the undefined dimension of a node. // - On a node with a set width/height aspect ratio control the size of the unset dimension // - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if // unset // - On a node with a measure function aspect ratio works as though the measure function measures // the flex basis // - On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if // unset // - Aspect ratio takes min/max dimensions into account YG_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio); YG_NODE_LAYOUT_PROPERTY(float, Left); YG_NODE_LAYOUT_PROPERTY(float, Top); YG_NODE_LAYOUT_PROPERTY(float, Right); YG_NODE_LAYOUT_PROPERTY(float, Bottom); YG_NODE_LAYOUT_PROPERTY(float, Width); YG_NODE_LAYOUT_PROPERTY(float, Height); YG_NODE_LAYOUT_PROPERTY(YGDirection, Direction); WIN_EXPORT void YGSetLogger(YGLogger logger); WIN_EXPORT void YGLog(YGLogLevel level, const char *message, ...); WIN_EXPORT void YGSetExperimentalFeatureEnabled(YGExperimentalFeature feature, bool enabled); WIN_EXPORT bool YGIsExperimentalFeatureEnabled(YGExperimentalFeature feature); WIN_EXPORT void YGSetMemoryFuncs(YGMalloc ygmalloc, YGCalloc yccalloc, YGRealloc ygrealloc, YGFree ygfree); YG_EXTERN_C_END ================================================ FILE: FlexBoxLayout/Classes/Transaction/FBAsyLayoutTransaction.h ================================================ // // FBAsyLayoutTransaction.h // CSJSView // // Created by 沈强 on 2016/8/31. // Copyright © 2016年 沈强. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FBAsyLayoutTransaction : NSObject /** asy calculate transaction @param transaction transaction task @param complete task complete */ + (void)addCalculateTransaction:(dispatch_block_t)transaction complete:(nullable dispatch_block_t)complete; + (void)addDisplayTransaction:(dispatch_block_t)transaction complete:(dispatch_block_t)complete; @end NS_ASSUME_NONNULL_END ================================================ FILE: FlexBoxLayout/Classes/Transaction/FBAsyLayoutTransaction.m ================================================ // // FBAsyLayoutTransaction.m // CSJSView // // Created by 沈强 on 2016/8/31. // Copyright © 2016年 沈强. All rights reserved. // #import "FBAsyLayoutTransaction.h" #import #import #import static NSMutableArray *messageQueue = nil; static CFRunLoopSourceRef _runLoopSource = nil; static dispatch_queue_t calculate_creation_queue() { static dispatch_queue_t calculate_creation_queue; static dispatch_once_t creationOnceToken; dispatch_once(&creationOnceToken, ^{ calculate_creation_queue = dispatch_queue_create("flexbox.calculateLayout", DISPATCH_QUEUE_SERIAL); }); return calculate_creation_queue; } static void display_Locked(dispatch_block_t block) { if ([UIDevice currentDevice].systemVersion.floatValue >= 10.0) { static os_unfair_lock lockToken = OS_UNFAIR_LOCK_INIT; os_unfair_lock_lock(&lockToken); block(); os_unfair_lock_unlock(&lockToken); } else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" static OSSpinLock lockToken = OS_SPINLOCK_INIT; OSSpinLockLock(&lockToken); block(); OSSpinLockUnlock(&lockToken); #pragma clang diagnostic pop } } static void enqueue(dispatch_block_t block) { display_Locked(^() { if (!messageQueue) { messageQueue = [NSMutableArray array]; } [messageQueue addObject:block]; CFRunLoopSourceSignal(_runLoopSource); CFRunLoopWakeUp(CFRunLoopGetMain()); }); } static void processQueue() { display_Locked(^{ for (dispatch_block_t block in messageQueue) { block(); } [messageQueue removeAllObjects]; }); } static void calculate_create_task_safely(dispatch_block_t block, dispatch_block_t complete) { dispatch_async(calculate_creation_queue(), ^ { block(); enqueue(complete); }); } static void sourceContextCallBackLog(void *info) { #if DEBUG NSLog(@"applay FlexBox layout"); #endif } static void _messageGroupRunLoopObserverCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) { processQueue(); } #define MAX_CONCURRENT_COUNT 8 static dispatch_semaphore_t FBConcurrentSemaphore; static dispatch_queue_t display_creation_queue() { static dispatch_queue_t dispalyQueue = NULL; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ dispalyQueue = dispatch_queue_create("flexbox.display", DISPATCH_QUEUE_CONCURRENT); dispatch_set_target_queue(dispalyQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)); }); return dispalyQueue; } static void display_create_task_safely(dispatch_block_t displayBlock, dispatch_block_t complete) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSUInteger processorCount = [NSProcessInfo processInfo].activeProcessorCount; NSUInteger maxConcurrentCount = processorCount <= MAX_CONCURRENT_COUNT ? processorCount : MAX_CONCURRENT_COUNT; FBConcurrentSemaphore = dispatch_semaphore_create(maxConcurrentCount); }); dispatch_async(display_creation_queue(), ^{ dispatch_semaphore_wait(FBConcurrentSemaphore, DISPATCH_TIME_FOREVER); displayBlock(); enqueue(complete); dispatch_semaphore_signal(FBConcurrentSemaphore); }); } @implementation FBAsyLayoutTransaction + (void)load { CFRunLoopObserverRef observer; CFRunLoopRef runLoop = CFRunLoopGetMain(); CFOptionFlags activities = (kCFRunLoopBeforeWaiting | kCFRunLoopExit); observer = CFRunLoopObserverCreate(NULL, activities, YES, INT_MAX, &_messageGroupRunLoopObserverCallback, NULL); if (observer) { CFRunLoopAddObserver(runLoop, observer, kCFRunLoopCommonModes); CFRelease(observer); } CFRunLoopSourceContext *sourceContext = calloc(1, sizeof(CFRunLoopSourceContext)); sourceContext->perform = &sourceContextCallBackLog; _runLoopSource = CFRunLoopSourceCreate(NULL, 0, sourceContext); if (_runLoopSource) { CFRunLoopAddSource(runLoop, _runLoopSource, kCFRunLoopCommonModes); } } + (void)addCalculateTransaction:(dispatch_block_t)transaction complete:(dispatch_block_t)complete { calculate_create_task_safely(transaction, complete); } + (void)addDisplayTransaction:(dispatch_block_t)transaction complete:(dispatch_block_t)complete { display_create_task_safely(transaction, complete); } @end ================================================ FILE: FlexBoxLayout.podspec ================================================ Pod::Spec.new do |s| s.name = 'FlexBoxLayout' s.version = '1.0.0' s.summary = 'iOS Flexbox layout' s.description = <<-DESC iOS Flexbox layout. DESC s.homepage = 'https://github.com/carlSQ/FlexBoxLayout' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'carl' => '835150773@qq.com' } s.source = { :git => 'https://github.com/carlSQ/FlexBoxLayout.git', :tag => s.version.to_s } s.ios.deployment_target = '7.0' s.source_files = 'FlexBoxLayout/Classes/**/*' end ================================================ FILE: LICENSE ================================================ Copyright (c) 2017 qiang.shen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # FlexBoxLayout [![CI Status](http://img.shields.io/travis/LPD-iOS/FlexBoxLayout.svg?style=flat)](https://travis-ci.org/carlSQ/FlexBoxLayout) [![Version](https://img.shields.io/cocoapods/v/FlexBoxLayout.svg?style=flat)](http://cocoapods.org/pods/FlexBoxLayout) [![License](https://img.shields.io/cocoapods/l/FlexBoxLayout.svg?style=flat)](http://cocoapods.org/pods/FlexBoxLayout) [![Platform](https://img.shields.io/cocoapods/p/FlexBoxLayout.svg?style=flat)](http://cocoapods.org/pods/FlexBoxLayout) ## 特点 * Flexbox Layout; * 链式调用,布局方便; * 虚拟视图 Div; * TableView 支持自动高度、布局缓存,contentView 缓存,和自动 cache 失效机制; * ScrollView 支持自适应 contentSize; * 异步计算布局。 ## 预览 ![](https://github.com/LPD-iOS/FlexBoxLayout/blob/master/Example/Example/show.gif) ## 示例 1. 利用 `git clone` 命令下载本仓库, `Examples` 目录包含了示例程序; 2. 用 XCode 打开对应项目编译即可。 或执行以下命令: ```bash git clone git@github.com:LPD-iOS/FlexBoxLayout.git; cd FlexBoxLayout/Example; open 'FlexBoxLayout.xcworkspace' ``` ## 安装 FlexBoxLayout 可以通过 [CocoaPods](http://cocoapods.org) 进行获取。只需要在你的 Podfile 中添加如下代码就能实现引入: ```ruby pod "FlexBoxLayout" ``` 然后,执行如下命令即可: ```bash $ pod install ``` ## 示例代码 ```objc - (void)layoutView { [self fb_makeLayout:^(FBLayout *layout) { layout.flexDirection.equalTo(@(FBFlexDirectionColumn)).margin.equalToEdgeInsets(UIEdgeInsetsMake(0, 15, 0, 15)).alignItems.equalTo(@(FBAlignFlexStart)); }]; [_titleLabel fb_makeLayout:^(FBLayout *layout) { layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)).wrapContent(); }] ; [_contentLabel fb_makeLayout:^(FBLayout *layout) { layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)).wrapContent(); }]; [_contentImageView fb_makeLayout:^(FBLayout *layout) { layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)).wrapContent(); }]; [_usernameLabel fb_makeLayout:^(FBLayout *layout) { layout.wrapContent().flexGrow.equalTo(@(1.0)); }]; [_timeLabel fb_makeLayout:^(FBLayout *layout) { layout.wrapContent().flexGrow.equalTo(@(1.0)); }]; FBLayoutDiv *div = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionRow ]; [div fb_makeLayout:^(FBLayout *layout) { layout.flexDirection.equalTo(@(FBFlexDirectionRow)).justifyContent.equalTo(@(FBJustifySpaceBetween)).alignItems.equalTo(@(FBAlignFlexStart)).margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)); }]; div.fb_children = @[_usernameLabel,_timeLabel]; self.fb_children =@[_titleLabel,_contentLabel,_contentImageView,div]; } ``` ## 使用 These are some flexbox introduce [FlexBox(Chinese)](http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html), [A Complete Guide to Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) and [A Visual Guide to CSS3 Flexbox Properties](https://scotch.io/tutorials/a-visual-guide-to-css3-flexbox-properties)。 ### 1. UIView + FBLayout Usage Here are some simple uses ```objc UIScrollView *contentView = [UIScrollView new]; contentView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-44); [self.view addSubview:contentView]; UIView *child1 = [UIView new]; child1.backgroundColor = [UIColor blueColor]; [child1 fb_makeLayout:^(FBLayout *layout) { layout.width.height.equalTo(@100); }]; UIView *child2 = [UIView new]; child2.backgroundColor = [UIColor greenColor]; [child2 fb_makeLayout:^(FBLayout *layout) { layout.equalTo(child1); }]; UILabel *child3 = [UILabel new]; child3.numberOfLines = 0; child3.backgroundColor = [UIColor yellowColor]; [child3 fb_wrapContent]; [child3 setAttributedText:[[NSAttributedString alloc] initWithString:@"testfdsfdsfdsfdsfdsfdsafdsafdsafasdkkk" attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:18]}] ]; [contentView addSubview:child1]; [contentView addSubview:child2]; [contentView addSubview:child3]; FBLayoutDiv *div1 = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn justifyContent:FBJustifySpaceBetween alignItems:FBAlignCenter children:@[child1, child2,child3]]; [div1 fb_makeLayout:^(FBLayout *layout) { layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(20, 0, 0, 0)); layout.width.equalTo(@(150)); }]; UIView *child5 = [UIView new]; child5.backgroundColor = [UIColor blueColor]; child5.CSSStyles = @{FBWidthAttributeName:@(50), FBHeightAttributeName:@(50), FBMarginAttributeName:[NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(0, 0, 10, 0)], FBFlexGrowAttributeName:@1.0}; UIView *child6 = [UIView new]; child6.backgroundColor = [UIColor greenColor]; [child6 fb_makeLayout:^(FBLayout *layout) { layout.equalTo(child5); layout.flexGrow.equalTo(@(2.0)); layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 10, 10, 10)); }]; UIView *child7 = [UIView new]; child7.backgroundColor = [UIColor yellowColor]; [child7 fb_makeLayout:^(FBLayout *layout) { layout.equalTo(child5); }]; UIView *child8 = [UIView new]; child8.backgroundColor = [UIColor blackColor]; [child8 fb_makeLayout:^(FBLayout *layout) { layout.equalTo(child5); }]; FBLayoutDiv *div2 =[FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn justifyContent:FBJustifySpaceAround alignItems:FBAlignCenter children:@[child5,child6,child7,child8]]; [div2 fb_makeLayout:^(FBLayout *layout) { layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(20, 0, 0, 0)); layout.width.equalTo(@(150)); }]; [contentView addSubview:child5]; [contentView addSubview:child6]; [contentView addSubview:child7]; [contentView addSubview:child8]; FBLayoutDiv *root = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionRow justifyContent:FBJustifySpaceAround alignItems:FBAlignCenter children:@[div1,div2]]; contentView.fb_contentDiv = root; [root fb_asyApplyLayoutWithSize:[UIScreen mainScreen].bounds.size]; ``` ### 2. FBLayoutDiv FBLayoutDiv is virtual view, split view to a different area, avoid too much view. ```objc FBLayoutDiv *div1 = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn justifyContent:FBJustifySpaceBetween alignItems:FBAlignCenter children:@[child1, child2,child3]]; FBLayoutDiv *div2 =[FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn justifyContent:FBJustifySpaceAround alignItems:FBAlignCenter children:@[child5,child6,child7,child8]]; root.fb_children = @[div1,div2]; ``` ### 3. UITableView+FBLayout UITableView+FBLayout is category of UITableView. It support auto cell height of FBLayout and easy use. ```objc [self.tableView fb_setCellContnetViewBlockForIndexPath:^UIView *(NSIndexPath *indexPath) { return [[FBFeedView alloc]initWithModel:weakSelf.sections[indexPath.section][indexPath.row]]; }]; .... - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return [self.tableView fb_heightForIndexPath:indexPath]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { return [self.tableView fb_cellForIndexPath:indexPath]; } ``` ### 4. UIScrollView+FBLayout It support auto content size: ```objc FBLayoutDiv *root = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionRow justifyContent:FBJustifySpaceAround alignItems:FBAlignCenter children:@[div1,div2]]; contentView.fb_contentDiv = root; ``` ### 5. Flexbox container properties #### 5.1 flex-direction This property specifies how flex items are laid out in the flex container, by setting the direction of the flex container’s main axis. They can be laid out in two main directions, like rows horizontally or like columns vertically. ```objc FBFlexDirectionRow; ``` ![ROW](https://cask.scotch.io/2015/04/flexbox-flex-direction-row.jpg) ```objc FBFlexDirectionRowReverse; ``` ![RowReverse](https://cask.scotch.io/2015/04/flexbox-flex-direction-row-reverse.jpg) ```objc FBFlexDirectionColumn; ``` ![Colum](https://cask.scotch.io/2015/04/flexbox-flex-direction-column.jpg) ```objc FBFlexDirectionColumnReverse; ``` ![ColumReverse](https://cask.scotch.io/2015/04/flexbox-flex-direction-column-reverse.jpg) #### 5.2 flex-wrap The initial flexbox concept is the container to set its items in one single line. The flex-wrap property controls if the flex container lay out its items in single or multiple lines, and the direction the new lines are stacked in.Supports only 'nowrap' (which is the default) or 'wrap' ```objc FBWrapNoWrap; ``` ![noWrap](https://cask.scotch.io/2015/04/flexbox-flex-wrap-nowrap.jpg) ```objc FBWrapWrap; ``` ![noWrap](https://cask.scotch.io/2015/04/flexbox-flex-wrap-wrap.jpg) #### 5.3 justify-content The justify-content property aligns flex items along the main axis of the current line of the flex container. It helps distribute left free space when either all the flex items on a line are inflexible, or are flexible but have reached their maximum size. ```objc FBJustifyFlexStart; ``` ![JustifyFlexStart](https://cask.scotch.io/2015/04/flexbox-justify-content-flex-start.jpg) ```objc FBJustifyCenter; ``` ![JustifyFlexStart](https://cask.scotch.io/2015/04/flexbox-justify-content-center.jpg) ```objc FBJustifyFlexEnd ``` ![JustifyFlexStart](https://cask.scotch.io/2015/04/flexbox-justify-content-flex-end.jpg) ```objc FBJustifySpaceBetween; ``` ![JustifyFlexStart](https://cask.scotch.io/2015/04/flexbox-justify-content-space-between.jpg) ```objc FBJustifySpaceAround; ``` ![JustifyFlexStart](https://cask.scotch.io/2015/04/flexbox-justify-content-space-around.jpg) #### 5.4 align-items Flex items can be aligned in the cross axis of the current line of the flex container, similar to justify-content but in the perpendicular direction. This property sets the default alignment for all flex items, including the anonymous ones. ```objc FBAlignFlexStart; ``` ![CSSAlignFlexStart](https://cask.scotch.io/2015/04/flexbox-align-items-flex-start.jpg) ```objc FBAlignCenter; ``` ![CSSAlignCenter](https://cask.scotch.io/2015/04/flexbox-align-items-center.jpg) ```objc FBAlignFlexEnd; ``` ![CSSAlignFlexEnd](https://cask.scotch.io/2015/04/flexbox-align-items-flex-end.jpg) ```objc FBAlignStretch; ``` ![CSSAlignStretch](https://cask.scotch.io/2015/04/flexbox-align-items-stretch.jpg) #### 5.5 align-content The align-content property aligns a flex container’s lines within the flex container when there is extra space in the cross-axis, similar to how justify-content aligns individual items within the main-axis. ```objc FBAlignFlexStart; ``` ![CSSAlignFlexStart](https://cask.scotch.io/2015/04/flexbox-align-content-flex-start.jpg) ```objc FBAlignCenter; ``` ![CSSAlignFlexStart](https://cask.scotch.io/2015/04/flexbox-align-content-center.jpg) ```objc FBAlignFlexEnd; ``` ![CSSAlignFlexStart](https://cask.scotch.io/2015/04/flexbox-align-content-flex-end.jpg) ```objc FBAlignStretch; ``` ![CSSAlignFlexStart](https://cask.scotch.io/2015/04/flexbox-align-content-stretch.jpg) ### 6. Flexbox item properties #### 6.1 flex-grow This property specifies the flex grow factor, which determines how much the flex item will grow relative to the rest of the flex items in the flex container when positive free space is distributed. ```objc FlexGrow; ``` ![FlexGrow-1.0](https://cask.scotch.io/2015/04/flexbox-flex-grow-1.jpg) ![FlexGrow-3.0](https://cask.scotch.io/2015/04/flexbox-flex-grow-2.jpg) #### 6.2 flex-shrink The flex-shrink specifies the flex shrink factor, which determines how much the flex item will shrink relative to the rest of the flex items in the flex container when negative free space is distributed. By default all flex items can be shrunk, but if we set it to 0 (don’t shrink) they will maintain the original size ```objc FlexShrink; ``` ![flex-shrink](https://cask.scotch.io/2015/04/flexbox-flex-shrink.jpg) #### 6.3 flex-basis This property takes the same values as the width and height properties, and specifies the initial main size of the flex item, before free space is distributed according to the flex factors. ```objc FlexBasis:350; ``` ![flex-basis](https://cask.scotch.io/2015/04/flexbox-flex-basis.jpg) #### 6.4 align-self This align-self property allows the default alignment (or the one specified by align-items) to be overridden for individual flex items. Refer to align-items explanation for flex container to understand the available values. ```objc FBAlignFlexStart; ``` ![align-self](https://cask.scotch.io/2015/04/flexbox-align-self.jpg) ## 作者 qiang.shen ## 协议 ![](https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/License_icon-mit-88x31-2.svg/128px-License_icon-mit-88x31-2.svg.png) FlexBoxLayout 基于 MIT 协议进行分发和使用,更多信息参见协议文件。