[YogaKit] Fix layout view with yoga disabled #951

Closed
lucasaraujo wants to merge 3 commits from master into main
2 changed files with 27 additions and 2 deletions
Showing only changes of commit 4dac11a82e - Show all commits

58
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
name: CI
on: [push, pull_request]
jobs:
website:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 8.x
- name: Install dependencies
run: yarn install --frozen-lockfile --ignore-scripts
working-directory: website
- name: Build
run: yarn build
working-directory: website
- name: Deploy
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: gh-pages
publish_dir: website/public
cname: yogalayout.com
keep_files: true
user_name: 'Yoga-bot'
user_email: 'yogabot@fb.com'
android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Install NDK 21
run: echo "y" | sudo /usr/local/lib/android/sdk/tools/bin/sdkmanager --install "ndk;21.0.6113669" "ndk;20.0.5594570" --sdk_root=${ANDROID_SDK_ROOT}
- name: Install dependencies
run: |
if [[ -n "${{ secrets.encrypted_d27e803291ff_iv }}" ]]; then
openssl aes-256-cbc -K ${{ secrets.encrypted_d27e803291ff_key }} -iv {{ secrets.encrypted_d27e803291ff_iv }} -in scripts/setup-keys.enc -d >> gradle.properties;
fi
sudo apt-get update
sudo apt-get install -y ninja-build
pushd $HOME
git clone --depth 1 https://github.com/facebook/buck.git
cd buck
ant
popd
echo "$HOME/buck/bin" >> $GITHUB_PATH
export PATH=$PATH:$HOME/buck/bin/
buck --version
- name: Build
# TODO: Run the tests here again. They're currently crashing the JVM in GitHub Actions for some reason.
run: ./gradlew :yoga-layout:assembleDebug

32
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: Publish
on:
release:
types:
- created
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Install dependencies
run: source scripts/android-setup.sh && installAndroidSDK
- name: Write GPG Sec Ring
run: echo '${{ secrets.GPG_KEY_CONTENTS }}' | base64 -d > /tmp/secring.gpg
- name: Update gradle.properties
run: echo -e "signing.secretKeyRingFile=/tmp/secring.gpg\nsigning.keyId=${{ secrets.SIGNING_KEY_ID }}\nsigning.password=${{ secrets.SIGNING_PASSWORD }}\nmavenCentralPassword=${{ secrets.SONATYPE_NEXUS_PASSWORD }}\nmavenCentralUsername=${{ secrets.SONATYPE_NEXUS_USERNAME }}" >> gradle.properties
- name: Upload Android Archives
run: ./gradlew :yoga:assembleRelease publish --info
- name: Release and close
run: ./gradlew closeAndReleaseRepository
- name: Clean secrets
if: always()
run: rm /tmp/secring.gpg

3
.gitignore vendored
View File

@@ -6,6 +6,9 @@
/.buckd /.buckd
/gentest/test.html /gentest/test.html
.buckversion .buckversion
.cxx
.idea
/local.properties
# Jekyll # Jekyll
/.sass-cache/ /.sass-cache/

View File

@@ -1,77 +0,0 @@
language: java
os: linux
dist: trusty
addons:
apt:
sources:
- llvm-toolchain-trusty-6.0
- ubuntu-toolchain-r-test
packages:
- clang-6.0
env:
- TARGET: website
- TARGET: android
install:
- cd website
- yarn --ignore-scripts
- cd ..
cache:
directories:
- $HOME/buck
- $HOME/.gradle
before_install:
- |
if [[ -n "$encrypted_d27e803291ff_iv" ]]; then
openssl aes-256-cbc -K $encrypted_d27e803291ff_key -iv $encrypted_d27e803291ff_iv -in scripts/setup-keys.enc -d >> gradle.properties;
fi
# Android
- |
if [[ $TARGET = "android" ]]; then
pushd $HOME
git clone --depth 1 https://github.com/facebook/buck.git
cd buck
ant
popd
export PATH=$PATH:$HOME/buck/bin/
buck --version
export TERMINAL=dumb
source scripts/android-setup.sh && installAndroidSDK
export ANDROID_SDK=$ANDROID_HOME
export ANDROID_NDK_REPOSITORY=$HOME/android-ndk
export ANDROID_NDK_HOME=$ANDROID_NDK_REPOSITORY/android-ndk-r15c
fi
# Website
- |
if [[ $TARGET = "website" ]]; then
nvm install 8
nvm use 8
fi
script:
- |
if [[ $TARGET = "android" ]]; then
./gradlew testDebugUnit && scripts/publish-snapshot.sh
fi
- |
if [[ $TARGET = "website" ]]; then
pushd website
yarn build
popd
fi
deploy:
provider: pages
skip-cleanup: true
github-token: $GITHUB_TOKEN
fqdn: yogalayout.com
local-dir: website/public
email: yogabot@fb.com
name: Yoga-bot
keep-history: true
on:
branch: master
condition: $TARGET = website

14
BUCK
View File

@@ -40,6 +40,20 @@ yoga_cxx_library(
], ],
) )
yoga_cxx_library(
name = "yoga-static",
srcs = glob(["yoga/**/*.cpp"]),
compiler_flags = LIBRARY_COMPILER_FLAGS,
preferred_linkage = "static",
public_include_directories = ["."],
raw_headers = glob(["yoga/**/*.h"]),
tests = [":YogaTests"],
visibility = ["PUBLIC"],
deps = [
":ndklog",
],
)
yoga_cxx_library( yoga_cxx_library(
name = "yogaForDebug", name = "yogaForDebug",
srcs = glob(["yoga/**/*.cpp"]), srcs = glob(["yoga/**/*.cpp"]),

View File

@@ -46,3 +46,29 @@ This will now only run the standalone webpack build upon install.
| node | Builds node js version. | | node | Builds node js version. |
| standalone | Runs webpack. | | standalone | Runs webpack. |
| none | Does nothing. You can use the prepackaged libs. | | none | Does nothing. You can use the prepackaged libs. |
## Maintainer Release Guide
To publish a new release, follow these steps:
1. Ensure you have your GPG key set up and your [OSS Sonatype](https://oss.sonatype.org/) credentials handy.
2. Add the follow entries to either your local `gradle.properties` (don't forget to revert) or your global `~/.gradle/gradle.properties`:
```
# You get these from https://oss.sonatype.org/#profile;User%20Token
mavenCentralRepositoryUsername=<username>
mavenCentralRepositoryPassword=<password>
# You can get the keyId (in GPG 1.4 format) by running `gpg1 --list-keys`.
signing.secretKeyRingFile=</path/to/secring.gpg>
signing.keyId=<key_id>
signing.password=<key_password>
```
3. Change the `VERSION_NAME` in `gradle.properties` to a non-SNAPSHOT release.
4. Commit and land the version change.
5. Run `./gradlew publishToMaven`.
6. Run `./gradlew closeAndReleaseRepository`.
7. Change the `VERSION_NAME` in `gradle.properties` back to a new SNAPSHOT release.
8. Commit and land the version change.
9. Celebrate! You've made a release!

View File

@@ -191,7 +191,6 @@
27595AD71E575C7800CCE2B1 /* SampleCxxModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0D41E03699D0018521A /* SampleCxxModule.h */; }; 27595AD71E575C7800CCE2B1 /* SampleCxxModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0D41E03699D0018521A /* SampleCxxModule.h */; };
27595AD81E575C7800CCE2B1 /* SystraceSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0D51E03699D0018521A /* SystraceSection.h */; }; 27595AD81E575C7800CCE2B1 /* SystraceSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0D51E03699D0018521A /* SystraceSection.h */; };
2D0EB9F32021067800CAF88A /* RCTUIUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = F1EFDA4E201F660F00EE6E4C /* RCTUIUtils.m */; }; 2D0EB9F32021067800CAF88A /* RCTUIUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = F1EFDA4E201F660F00EE6E4C /* RCTUIUtils.m */; };
2D16E68E1FA4FD3900B85C8A /* RCTTVNavigationEventEmitter.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D0B842D1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.h */; };
2D1D83CE1F74E2DA00615550 /* libdouble-conversion.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D383D621EBD27B9005632C8 /* libdouble-conversion.a */; }; 2D1D83CE1F74E2DA00615550 /* libdouble-conversion.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D383D621EBD27B9005632C8 /* libdouble-conversion.a */; };
2D3B5E931D9B087300451313 /* RCTErrorInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */; }; 2D3B5E931D9B087300451313 /* RCTErrorInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */; };
2D3B5E941D9B087900451313 /* RCTBundleURLProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 68EFE4ED1CF6EB3900A1DE13 /* RCTBundleURLProvider.m */; }; 2D3B5E941D9B087900451313 /* RCTBundleURLProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 68EFE4ED1CF6EB3900A1DE13 /* RCTBundleURLProvider.m */; };
@@ -269,8 +268,6 @@
3D0B842A1EC0B49400B2BD8E /* RCTTVRemoteHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0B84281EC0B49400B2BD8E /* RCTTVRemoteHandler.h */; }; 3D0B842A1EC0B49400B2BD8E /* RCTTVRemoteHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0B84281EC0B49400B2BD8E /* RCTTVRemoteHandler.h */; };
3D0B842B1EC0B49400B2BD8E /* RCTTVRemoteHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D0B84291EC0B49400B2BD8E /* RCTTVRemoteHandler.m */; }; 3D0B842B1EC0B49400B2BD8E /* RCTTVRemoteHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D0B84291EC0B49400B2BD8E /* RCTTVRemoteHandler.m */; };
3D0B842C1EC0B4EA00B2BD8E /* RCTTVView.m in Sources */ = {isa = PBXBuildFile; fileRef = 130443D71E401AD800D93A67 /* RCTTVView.m */; }; 3D0B842C1EC0B4EA00B2BD8E /* RCTTVView.m in Sources */ = {isa = PBXBuildFile; fileRef = 130443D71E401AD800D93A67 /* RCTTVView.m */; };
3D0B842F1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0B842D1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.h */; };
3D0B84301EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D0B842E1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.m */; };
3D0E378A1F1CC40000DCAC9F /* RCTWebSocketModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0E37891F1CC40000DCAC9F /* RCTWebSocketModule.h */; }; 3D0E378A1F1CC40000DCAC9F /* RCTWebSocketModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0E37891F1CC40000DCAC9F /* RCTWebSocketModule.h */; };
3D0E378E1F1CC59100DCAC9F /* RCTWebSocketModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0E37891F1CC40000DCAC9F /* RCTWebSocketModule.h */; }; 3D0E378E1F1CC59100DCAC9F /* RCTWebSocketModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0E37891F1CC40000DCAC9F /* RCTWebSocketModule.h */; };
3D0E378F1F1CC5CF00DCAC9F /* RCTWebSocketModule.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D0E37891F1CC40000DCAC9F /* RCTWebSocketModule.h */; }; 3D0E378F1F1CC5CF00DCAC9F /* RCTWebSocketModule.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D0E37891F1CC40000DCAC9F /* RCTWebSocketModule.h */; };
@@ -1275,7 +1272,6 @@
594F0A471FD233BD007FBE96 /* RCTSurfaceView.h in Copy Headers */, 594F0A471FD233BD007FBE96 /* RCTSurfaceView.h in Copy Headers */,
594F0A481FD233BD007FBE96 /* RCTSurfaceHostingView.h in Copy Headers */, 594F0A481FD233BD007FBE96 /* RCTSurfaceHostingView.h in Copy Headers */,
594F0A491FD233BD007FBE96 /* RCTSurfaceSizeMeasureMode.h in Copy Headers */, 594F0A491FD233BD007FBE96 /* RCTSurfaceSizeMeasureMode.h in Copy Headers */,
2D16E68E1FA4FD3900B85C8A /* RCTTVNavigationEventEmitter.h in Copy Headers */,
59500D481F71C67600B122B7 /* RCTUIManagerUtils.h in Copy Headers */, 59500D481F71C67600B122B7 /* RCTUIManagerUtils.h in Copy Headers */,
3D0E37901F1CC5E100DCAC9F /* RCTWebSocketModule.h in Copy Headers */, 3D0E37901F1CC5E100DCAC9F /* RCTWebSocketModule.h in Copy Headers */,
5960C1BF1F0804F50066FD5B /* RCTLayoutAnimation.h in Copy Headers */, 5960C1BF1F0804F50066FD5B /* RCTLayoutAnimation.h in Copy Headers */,
@@ -1876,8 +1872,6 @@
39C50FFA2046EE3500CEE534 /* RCTVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTVersion.m; sourceTree = "<group>"; }; 39C50FFA2046EE3500CEE534 /* RCTVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTVersion.m; sourceTree = "<group>"; };
3D0B84281EC0B49400B2BD8E /* RCTTVRemoteHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTVRemoteHandler.h; sourceTree = "<group>"; }; 3D0B84281EC0B49400B2BD8E /* RCTTVRemoteHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTVRemoteHandler.h; sourceTree = "<group>"; };
3D0B84291EC0B49400B2BD8E /* RCTTVRemoteHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTVRemoteHandler.m; sourceTree = "<group>"; }; 3D0B84291EC0B49400B2BD8E /* RCTTVRemoteHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTVRemoteHandler.m; sourceTree = "<group>"; };
3D0B842D1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTVNavigationEventEmitter.h; sourceTree = "<group>"; };
3D0B842E1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTVNavigationEventEmitter.m; sourceTree = "<group>"; };
3D0E37891F1CC40000DCAC9F /* RCTWebSocketModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTWebSocketModule.h; path = WebSocket/RCTWebSocketModule.h; sourceTree = "<group>"; }; 3D0E37891F1CC40000DCAC9F /* RCTWebSocketModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTWebSocketModule.h; path = WebSocket/RCTWebSocketModule.h; sourceTree = "<group>"; };
3D1E68D81CABD13900DD7465 /* RCTDisplayLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDisplayLink.h; sourceTree = "<group>"; }; 3D1E68D81CABD13900DD7465 /* RCTDisplayLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDisplayLink.h; sourceTree = "<group>"; };
3D1E68D91CABD13900DD7465 /* RCTDisplayLink.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDisplayLink.m; sourceTree = "<group>"; }; 3D1E68D91CABD13900DD7465 /* RCTDisplayLink.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDisplayLink.m; sourceTree = "<group>"; };
@@ -2346,8 +2340,6 @@
0EEEA8DE2239002200A8C82D /* RCTSurfacePresenterStub.m */, 0EEEA8DE2239002200A8C82D /* RCTSurfacePresenterStub.m */,
13B07FED1A69327A00A75B9A /* RCTTiming.h */, 13B07FED1A69327A00A75B9A /* RCTTiming.h */,
13B07FEE1A69327A00A75B9A /* RCTTiming.m */, 13B07FEE1A69327A00A75B9A /* RCTTiming.m */,
3D0B842D1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.h */,
3D0B842E1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.m */,
13E067481A70F434002CDEE1 /* RCTUIManager.h */, 13E067481A70F434002CDEE1 /* RCTUIManager.h */,
13E067491A70F434002CDEE1 /* RCTUIManager.m */, 13E067491A70F434002CDEE1 /* RCTUIManager.m */,
59EB6DB91EBD6FC90072A5E7 /* RCTUIManagerObserverCoordinator.h */, 59EB6DB91EBD6FC90072A5E7 /* RCTUIManagerObserverCoordinator.h */,
@@ -2945,7 +2937,6 @@
3D302F311DF828F800D6DDAE /* RCTBundleURLProvider.h in Headers */, 3D302F311DF828F800D6DDAE /* RCTBundleURLProvider.h in Headers */,
3D302F321DF828F800D6DDAE /* RCTConvert.h in Headers */, 3D302F321DF828F800D6DDAE /* RCTConvert.h in Headers */,
3D302F331DF828F800D6DDAE /* RCTDefines.h in Headers */, 3D302F331DF828F800D6DDAE /* RCTDefines.h in Headers */,
3D0B842F1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.h in Headers */,
3D302F341DF828F800D6DDAE /* RCTDisplayLink.h in Headers */, 3D302F341DF828F800D6DDAE /* RCTDisplayLink.h in Headers */,
3D302F351DF828F800D6DDAE /* RCTErrorCustomizer.h in Headers */, 3D302F351DF828F800D6DDAE /* RCTErrorCustomizer.h in Headers */,
3D302F361DF828F800D6DDAE /* RCTErrorInfo.h in Headers */, 3D302F361DF828F800D6DDAE /* RCTErrorInfo.h in Headers */,
@@ -3994,7 +3985,6 @@
2D3B5EC81D9B095800451313 /* RCTActivityIndicatorViewManager.m in Sources */, 2D3B5EC81D9B095800451313 /* RCTActivityIndicatorViewManager.m in Sources */,
3DCD185D1DF978E7007FE5A1 /* RCTReloadCommand.m in Sources */, 3DCD185D1DF978E7007FE5A1 /* RCTReloadCommand.m in Sources */,
130443DB1E401ADD00D93A67 /* RCTConvert+Transform.m in Sources */, 130443DB1E401ADD00D93A67 /* RCTConvert+Transform.m in Sources */,
3D0B84301EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.m in Sources */,
2D3B5EC61D9B095000451313 /* RCTProfileTrampoline-x86_64.S in Sources */, 2D3B5EC61D9B095000451313 /* RCTProfileTrampoline-x86_64.S in Sources */,
2D3B5EA61D9B08CA00451313 /* RCTTouchEvent.m in Sources */, 2D3B5EA61D9B08CA00451313 /* RCTTouchEvent.m in Sources */,
2D8C2E331DA40441000EE098 /* RCTMultipartStreamReader.m in Sources */, 2D8C2E331DA40441000EE098 /* RCTMultipartStreamReader.m in Sources */,

View File

@@ -33,6 +33,6 @@ Pod::Spec.new do |spec|
'-fPIC' '-fPIC'
] ]
spec.source_files = 'yoga/**/*.{c,h,cpp}' spec.source_files = 'yoga/**/*.{c,h,cpp}'
spec.public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGValue}.h' spec.public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGNode,YGStyle,YGValue}.h'
end end

View File

@@ -37,11 +37,14 @@ yoga_apple_library(
), ),
compiler_flags = COMPILER_FLAGS, compiler_flags = COMPILER_FLAGS,
frameworks = [ frameworks = [
"$SDKROOT/System/Library/Frameworks/CoreGraphics.framework",
"$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/Foundation.framework",
"$SDKROOT/System/Library/Frameworks/UIKit.framework", "$SDKROOT/System/Library/Frameworks/UIKit.framework",
], ],
header_path_prefix = "", header_path_prefix = "",
link_whole = True, link_whole = True,
modular = True,
module_name = "YogaKit",
visibility = ["PUBLIC"], visibility = ["PUBLIC"],
deps = [ deps = [
yoga_dep(":yoga"), yoga_dep(":yoga"),

View File

@@ -5,28 +5,29 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "YGLayout.h"
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import "YGLayout.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
typedef void (^YGLayoutConfigurationBlock)(YGLayout *layout); typedef void (^YGLayoutConfigurationBlock)(YGLayout* layout);
@interface UIView (Yoga) @interface UIView (Yoga)
/** /**
The YGLayout that is attached to this view. It is lazily created. The YGLayout that is attached to this view. It is lazily created.
*/ */
@property (nonatomic, readonly, strong) YGLayout *yoga; @property(nonatomic, readonly, strong) YGLayout* yoga;
/** /**
Indicates whether or not Yoga is enabled Indicates whether or not Yoga is enabled
*/ */
@property (nonatomic, readonly, assign) BOOL isYogaEnabled; @property(nonatomic, readonly, assign) BOOL isYogaEnabled;
/** /**
In ObjC land, every time you access `view.yoga.*` you are adding another `objc_msgSend` In ObjC land, every time you access `view.yoga.*` you are adding another
to your code. If you plan on making multiple changes to YGLayout, it's more performant `objc_msgSend` to your code. If you plan on making multiple changes to
to use this method, which uses a single objc_msgSend call. YGLayout, it's more performant to use this method, which uses a single
objc_msgSend call.
*/ */
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block - (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block
NS_SWIFT_NAME(configureLayout(block:)); NS_SWIFT_NAME(configureLayout(block:));

View File

@@ -5,32 +5,30 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import <objc/runtime.h>
#import "UIView+Yoga.h" #import "UIView+Yoga.h"
#import "YGLayout+Private.h" #import "YGLayout+Private.h"
#import <objc/runtime.h>
static const void *kYGYogaAssociatedKey = &kYGYogaAssociatedKey; static const void* kYGYogaAssociatedKey = &kYGYogaAssociatedKey;
@implementation UIView (YogaKit) @implementation UIView (YogaKit)
- (YGLayout *)yoga - (YGLayout*)yoga {
{ YGLayout* yoga = objc_getAssociatedObject(self, kYGYogaAssociatedKey);
YGLayout *yoga = objc_getAssociatedObject(self, kYGYogaAssociatedKey);
if (!yoga) { if (!yoga) {
yoga = [[YGLayout alloc] initWithView:self]; yoga = [[YGLayout alloc] initWithView:self];
objc_setAssociatedObject(self, kYGYogaAssociatedKey, yoga, OBJC_ASSOCIATION_RETAIN_NONATOMIC); objc_setAssociatedObject(
self, kYGYogaAssociatedKey, yoga, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
} }
return yoga; return yoga;
} }
- (BOOL)isYogaEnabled - (BOOL)isYogaEnabled {
{
return objc_getAssociatedObject(self, kYGYogaAssociatedKey) != nil; return objc_getAssociatedObject(self, kYGYogaAssociatedKey) != nil;
} }
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block - (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block {
{
if (block != nil) { if (block != nil) {
block(self.yoga); block(self.yoga);
} }

View File

@@ -5,13 +5,13 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "YGLayout.h"
#import <yoga/Yoga.h> #import <yoga/Yoga.h>
#import "YGLayout.h"
@interface YGLayout () @interface YGLayout ()
@property (nonatomic, assign, readonly) YGNodeRef node; @property(nonatomic, assign, readonly) YGNodeRef node;
- (instancetype)initWithView:(UIView *)view; - (instancetype)initWithView:(UIView*)view;
@end @end

View File

@@ -7,15 +7,15 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <yoga/YGEnums.h> #import <yoga/YGEnums.h>
#import <yoga/Yoga.h>
#import <yoga/YGMacros.h> #import <yoga/YGMacros.h>
#import <yoga/Yoga.h>
YG_EXTERN_C_BEGIN YG_EXTERN_C_BEGIN
extern YGValue YGPointValue(CGFloat value) extern YGValue YGPointValue(CGFloat value) NS_SWIFT_UNAVAILABLE(
NS_SWIFT_UNAVAILABLE("Use the swift Int and FloatingPoint extensions instead"); "Use the swift Int and FloatingPoint extensions instead");
extern YGValue YGPercentValue(CGFloat value) extern YGValue YGPercentValue(CGFloat value) NS_SWIFT_UNAVAILABLE(
NS_SWIFT_UNAVAILABLE("Use the swift Int and FloatingPoint extensions instead"); "Use the swift Int and FloatingPoint extensions instead");
YG_EXTERN_C_END YG_EXTERN_C_END
@@ -44,103 +44,107 @@ typedef NS_OPTIONS(NSInteger, YGDimensionFlexibility) {
The property that decides if we should include this view when calculating The property that decides if we should include this view when calculating
layout. Defaults to YES. layout. Defaults to YES.
*/ */
@property (nonatomic, readwrite, assign, setter=setIncludedInLayout:) BOOL isIncludedInLayout; @property(nonatomic, readwrite, assign, setter=setIncludedInLayout:)
BOOL isIncludedInLayout;
/** /**
The property that decides during layout/sizing whether or not styling properties should be applied. The property that decides during layout/sizing whether or not styling
Defaults to NO. properties should be applied. Defaults to NO.
*/ */
@property (nonatomic, readwrite, assign, setter=setEnabled:) BOOL isEnabled; @property(nonatomic, readwrite, assign, setter=setEnabled:) BOOL isEnabled;
@property (nonatomic, readwrite, assign) YGDirection direction; @property(nonatomic, readwrite, assign) YGDirection direction;
@property (nonatomic, readwrite, assign) YGFlexDirection flexDirection; @property(nonatomic, readwrite, assign) YGFlexDirection flexDirection;
@property (nonatomic, readwrite, assign) YGJustify justifyContent; @property(nonatomic, readwrite, assign) YGJustify justifyContent;
@property (nonatomic, readwrite, assign) YGAlign alignContent; @property(nonatomic, readwrite, assign) YGAlign alignContent;
@property (nonatomic, readwrite, assign) YGAlign alignItems; @property(nonatomic, readwrite, assign) YGAlign alignItems;
@property (nonatomic, readwrite, assign) YGAlign alignSelf; @property(nonatomic, readwrite, assign) YGAlign alignSelf;
@property (nonatomic, readwrite, assign) YGPositionType position; @property(nonatomic, readwrite, assign) YGPositionType position;
@property (nonatomic, readwrite, assign) YGWrap flexWrap; @property(nonatomic, readwrite, assign) YGWrap flexWrap;
@property (nonatomic, readwrite, assign) YGOverflow overflow; @property(nonatomic, readwrite, assign) YGOverflow overflow;
@property (nonatomic, readwrite, assign) YGDisplay display; @property(nonatomic, readwrite, assign) YGDisplay display;
@property (nonatomic, readwrite, assign) CGFloat flex; @property(nonatomic, readwrite, assign) CGFloat flex;
@property (nonatomic, readwrite, assign) CGFloat flexGrow; @property(nonatomic, readwrite, assign) CGFloat flexGrow;
@property (nonatomic, readwrite, assign) CGFloat flexShrink; @property(nonatomic, readwrite, assign) CGFloat flexShrink;
@property (nonatomic, readwrite, assign) YGValue flexBasis; @property(nonatomic, readwrite, assign) YGValue flexBasis;
@property (nonatomic, readwrite, assign) YGValue left; @property(nonatomic, readwrite, assign) YGValue left;
@property (nonatomic, readwrite, assign) YGValue top; @property(nonatomic, readwrite, assign) YGValue top;
@property (nonatomic, readwrite, assign) YGValue right; @property(nonatomic, readwrite, assign) YGValue right;
@property (nonatomic, readwrite, assign) YGValue bottom; @property(nonatomic, readwrite, assign) YGValue bottom;
@property (nonatomic, readwrite, assign) YGValue start; @property(nonatomic, readwrite, assign) YGValue start;
@property (nonatomic, readwrite, assign) YGValue end; @property(nonatomic, readwrite, assign) YGValue end;
@property (nonatomic, readwrite, assign) YGValue marginLeft; @property(nonatomic, readwrite, assign) YGValue marginLeft;
@property (nonatomic, readwrite, assign) YGValue marginTop; @property(nonatomic, readwrite, assign) YGValue marginTop;
@property (nonatomic, readwrite, assign) YGValue marginRight; @property(nonatomic, readwrite, assign) YGValue marginRight;
@property (nonatomic, readwrite, assign) YGValue marginBottom; @property(nonatomic, readwrite, assign) YGValue marginBottom;
@property (nonatomic, readwrite, assign) YGValue marginStart; @property(nonatomic, readwrite, assign) YGValue marginStart;
@property (nonatomic, readwrite, assign) YGValue marginEnd; @property(nonatomic, readwrite, assign) YGValue marginEnd;
@property (nonatomic, readwrite, assign) YGValue marginHorizontal; @property(nonatomic, readwrite, assign) YGValue marginHorizontal;
@property (nonatomic, readwrite, assign) YGValue marginVertical; @property(nonatomic, readwrite, assign) YGValue marginVertical;
@property (nonatomic, readwrite, assign) YGValue margin; @property(nonatomic, readwrite, assign) YGValue margin;
@property (nonatomic, readwrite, assign) YGValue paddingLeft; @property(nonatomic, readwrite, assign) YGValue paddingLeft;
@property (nonatomic, readwrite, assign) YGValue paddingTop; @property(nonatomic, readwrite, assign) YGValue paddingTop;
@property (nonatomic, readwrite, assign) YGValue paddingRight; @property(nonatomic, readwrite, assign) YGValue paddingRight;
@property (nonatomic, readwrite, assign) YGValue paddingBottom; @property(nonatomic, readwrite, assign) YGValue paddingBottom;
@property (nonatomic, readwrite, assign) YGValue paddingStart; @property(nonatomic, readwrite, assign) YGValue paddingStart;
@property (nonatomic, readwrite, assign) YGValue paddingEnd; @property(nonatomic, readwrite, assign) YGValue paddingEnd;
@property (nonatomic, readwrite, assign) YGValue paddingHorizontal; @property(nonatomic, readwrite, assign) YGValue paddingHorizontal;
@property (nonatomic, readwrite, assign) YGValue paddingVertical; @property(nonatomic, readwrite, assign) YGValue paddingVertical;
@property (nonatomic, readwrite, assign) YGValue padding; @property(nonatomic, readwrite, assign) YGValue padding;
@property (nonatomic, readwrite, assign) CGFloat borderLeftWidth; @property(nonatomic, readwrite, assign) CGFloat borderLeftWidth;
@property (nonatomic, readwrite, assign) CGFloat borderTopWidth; @property(nonatomic, readwrite, assign) CGFloat borderTopWidth;
@property (nonatomic, readwrite, assign) CGFloat borderRightWidth; @property(nonatomic, readwrite, assign) CGFloat borderRightWidth;
@property (nonatomic, readwrite, assign) CGFloat borderBottomWidth; @property(nonatomic, readwrite, assign) CGFloat borderBottomWidth;
@property (nonatomic, readwrite, assign) CGFloat borderStartWidth; @property(nonatomic, readwrite, assign) CGFloat borderStartWidth;
@property (nonatomic, readwrite, assign) CGFloat borderEndWidth; @property(nonatomic, readwrite, assign) CGFloat borderEndWidth;
@property (nonatomic, readwrite, assign) CGFloat borderWidth; @property(nonatomic, readwrite, assign) CGFloat borderWidth;
@property (nonatomic, readwrite, assign) YGValue width; @property(nonatomic, readwrite, assign) YGValue width;
@property (nonatomic, readwrite, assign) YGValue height; @property(nonatomic, readwrite, assign) YGValue height;
@property (nonatomic, readwrite, assign) YGValue minWidth; @property(nonatomic, readwrite, assign) YGValue minWidth;
@property (nonatomic, readwrite, assign) YGValue minHeight; @property(nonatomic, readwrite, assign) YGValue minHeight;
@property (nonatomic, readwrite, assign) YGValue maxWidth; @property(nonatomic, readwrite, assign) YGValue maxWidth;
@property (nonatomic, readwrite, assign) YGValue maxHeight; @property(nonatomic, readwrite, assign) YGValue maxHeight;
// Yoga specific properties, not compatible with flexbox specification // Yoga specific properties, not compatible with flexbox specification
@property (nonatomic, readwrite, assign) CGFloat aspectRatio; @property(nonatomic, readwrite, assign) CGFloat aspectRatio;
/** /**
Get the resolved direction of this node. This won't be YGDirectionInherit Get the resolved direction of this node. This won't be YGDirectionInherit
*/ */
@property (nonatomic, readonly, assign) YGDirection resolvedDirection; @property(nonatomic, readonly, assign) YGDirection resolvedDirection;
/** /**
Perform a layout calculation and update the frames of the views in the hierarchy with the results. Perform a layout calculation and update the frames of the views in the
If the origin is not preserved, the root view's layout results will applied from {0,0}. hierarchy with the results. If the origin is not preserved, the root view's
layout results will applied from {0,0}.
*/ */
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin - (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
NS_SWIFT_NAME(applyLayout(preservingOrigin:)); NS_SWIFT_NAME(applyLayout(preservingOrigin:));
/** /**
Perform a layout calculation and update the frames of the views in the hierarchy with the results. Perform a layout calculation and update the frames of the views in the
If the origin is not preserved, the root view's layout results will applied from {0,0}. hierarchy with the results. If the origin is not preserved, the root view's
layout results will applied from {0,0}.
*/ */
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin - (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
dimensionFlexibility:(YGDimensionFlexibility)dimensionFlexibility dimensionFlexibility:(YGDimensionFlexibility)dimensionFlexibility
NS_SWIFT_NAME(applyLayout(preservingOrigin:dimensionFlexibility:)); NS_SWIFT_NAME(applyLayout(preservingOrigin:dimensionFlexibility:));
/** /**
Returns the size of the view if no constraints were given. This could equivalent to calling [self Returns the size of the view if no constraints were given. This could
sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)]; equivalent to calling [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
*/ */
@property (nonatomic, readonly, assign) CGSize intrinsicSize; @property(nonatomic, readonly, assign) CGSize intrinsicSize;
/** /**
Returns the size of the view based on provided constraints. Pass NaN for an unconstrained dimension. Returns the size of the view based on provided constraints. Pass NaN for an
unconstrained dimension.
*/ */
- (CGSize)calculateLayoutWithSize:(CGSize)size - (CGSize)calculateLayoutWithSize:(CGSize)size
NS_SWIFT_NAME(calculateLayout(with:)); NS_SWIFT_NAME(calculateLayout(with:));
@@ -148,19 +152,19 @@ typedef NS_OPTIONS(NSInteger, YGDimensionFlexibility) {
/** /**
Returns the number of children that are using Flexbox. Returns the number of children that are using Flexbox.
*/ */
@property (nonatomic, readonly, assign) NSUInteger numberOfChildren; @property(nonatomic, readonly, assign) NSUInteger numberOfChildren;
/** /**
Return a BOOL indiciating whether or not we this node contains any subviews that are included in Return a BOOL indiciating whether or not we this node contains any subviews
Yoga's layout. that are included in Yoga's layout.
*/ */
@property (nonatomic, readonly, assign) BOOL isLeaf; @property(nonatomic, readonly, assign) BOOL isLeaf;
/** /**
Return's a BOOL indicating if a view is dirty. When a node is dirty Return's a BOOL indicating if a view is dirty. When a node is dirty
it usually indicates that it will be remeasured on the next layout pass. it usually indicates that it will be remeasured on the next layout pass.
*/ */
@property (nonatomic, readonly, assign) BOOL isDirty; @property(nonatomic, readonly, assign) BOOL isDirty;
/** /**
Mark that a view's layout needs to be recalculated. Only works for leaf views. Mark that a view's layout needs to be recalculated. Only works for leaf views.

View File

@@ -5,153 +5,184 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "YGLayout+Private.h"
#import "UIView+Yoga.h" #import "UIView+Yoga.h"
#import "YGLayout+Private.h"
#define YG_PROPERTY(type, lowercased_name, capitalized_name) \ #define YG_PROPERTY(type, lowercased_name, capitalized_name) \
- (type)lowercased_name \ -(type)lowercased_name { \
{ \ return YGNodeStyleGet##capitalized_name(self.node); \
return YGNodeStyleGet##capitalized_name(self.node); \ } \
} \ \
\ -(void)set##capitalized_name : (type)lowercased_name { \
- (void)set##capitalized_name:(type)lowercased_name \ YGNodeStyleSet##capitalized_name(self.node, lowercased_name); \
{ \ }
YGNodeStyleSet##capitalized_name(self.node, lowercased_name); \
#define YG_VALUE_PROPERTY(lowercased_name, capitalized_name) \
-(YGValue)lowercased_name { \
return YGNodeStyleGet##capitalized_name(self.node); \
} \
\
-(void)set##capitalized_name : (YGValue)lowercased_name { \
switch (lowercased_name.unit) { \
case YGUnitUndefined: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPoint: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##capitalized_name##Percent( \
self.node, lowercased_name.value); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_AUTO_VALUE_PROPERTY(lowercased_name, capitalized_name) \
-(YGValue)lowercased_name { \
return YGNodeStyleGet##capitalized_name(self.node); \
} \
\
-(void)set##capitalized_name : (YGValue)lowercased_name { \
switch (lowercased_name.unit) { \
case YGUnitPoint: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##capitalized_name##Percent( \
self.node, lowercased_name.value); \
break; \
case YGUnitAuto: \
YGNodeStyleSet##capitalized_name##Auto(self.node); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_EDGE_PROPERTY_GETTER( \
type, lowercased_name, capitalized_name, property, edge) \
-(type)lowercased_name { \
return YGNodeStyleGet##property(self.node, edge); \
}
#define YG_EDGE_PROPERTY_SETTER( \
lowercased_name, capitalized_name, property, edge) \
-(void)set##capitalized_name : (CGFloat)lowercased_name { \
YGNodeStyleSet##property(self.node, edge, lowercased_name); \
}
#define YG_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_GETTER( \
CGFloat, lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
#define YG_VALUE_EDGE_PROPERTY_SETTER( \
objc_lowercased_name, objc_capitalized_name, c_name, edge) \
-(void)set##objc_capitalized_name : (YGValue)objc_lowercased_name { \
switch (objc_lowercased_name.unit) { \
case YGUnitUndefined: \
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
break; \
case YGUnitPoint: \
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##c_name##Percent( \
self.node, edge, objc_lowercased_name.value); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_VALUE_EDGE_PROPERTY( \
lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_GETTER( \
YGValue, lowercased_name, capitalized_name, property, edge) \
YG_VALUE_EDGE_PROPERTY_SETTER( \
lowercased_name, capitalized_name, property, edge)
#define YG_VALUE_EDGES_PROPERTIES(lowercased_name, capitalized_name) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Left, \
capitalized_name##Left, \
capitalized_name, \
YGEdgeLeft) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Top, \
capitalized_name##Top, \
capitalized_name, \
YGEdgeTop) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Right, \
capitalized_name##Right, \
capitalized_name, \
YGEdgeRight) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Bottom, \
capitalized_name##Bottom, \
capitalized_name, \
YGEdgeBottom) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Start, \
capitalized_name##Start, \
capitalized_name, \
YGEdgeStart) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##End, \
capitalized_name##End, \
capitalized_name, \
YGEdgeEnd) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Horizontal, \
capitalized_name##Horizontal, \
capitalized_name, \
YGEdgeHorizontal) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Vertical, \
capitalized_name##Vertical, \
capitalized_name, \
YGEdgeVertical) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name, capitalized_name, capitalized_name, YGEdgeAll)
YGValue YGPointValue(CGFloat value) {
return (YGValue){.value = value, .unit = YGUnitPoint};
} }
#define YG_VALUE_PROPERTY(lowercased_name, capitalized_name) \ YGValue YGPercentValue(CGFloat value) {
- (YGValue)lowercased_name \ return (YGValue){.value = value, .unit = YGUnitPercent};
{ \
return YGNodeStyleGet##capitalized_name(self.node); \
} \
\
- (void)set##capitalized_name:(YGValue)lowercased_name \
{ \
switch (lowercased_name.unit) { \
case YGUnitUndefined: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPoint: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##capitalized_name##Percent(self.node, lowercased_name.value); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_AUTO_VALUE_PROPERTY(lowercased_name, capitalized_name) \
- (YGValue)lowercased_name \
{ \
return YGNodeStyleGet##capitalized_name(self.node); \
} \
\
- (void)set##capitalized_name:(YGValue)lowercased_name \
{ \
switch (lowercased_name.unit) { \
case YGUnitPoint: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##capitalized_name##Percent(self.node, lowercased_name.value); \
break; \
case YGUnitAuto: \
YGNodeStyleSet##capitalized_name##Auto(self.node); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_EDGE_PROPERTY_GETTER(type, lowercased_name, capitalized_name, property, edge) \
- (type)lowercased_name \
{ \
return YGNodeStyleGet##property(self.node, edge); \
}
#define YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge) \
- (void)set##capitalized_name:(CGFloat)lowercased_name \
{ \
YGNodeStyleSet##property(self.node, edge, lowercased_name); \
}
#define YG_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_GETTER(CGFloat, lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
#define YG_VALUE_EDGE_PROPERTY_SETTER(objc_lowercased_name, objc_capitalized_name, c_name, edge) \
- (void)set##objc_capitalized_name:(YGValue)objc_lowercased_name \
{ \
switch (objc_lowercased_name.unit) { \
case YGUnitUndefined: \
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
break; \
case YGUnitPoint: \
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##c_name##Percent(self.node, edge, objc_lowercased_name.value); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_VALUE_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_GETTER(YGValue, lowercased_name, capitalized_name, property, edge) \
YG_VALUE_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
#define YG_VALUE_EDGES_PROPERTIES(lowercased_name, capitalized_name) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Left, capitalized_name##Left, capitalized_name, YGEdgeLeft) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Top, capitalized_name##Top, capitalized_name, YGEdgeTop) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Right, capitalized_name##Right, capitalized_name, YGEdgeRight) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Bottom, capitalized_name##Bottom, capitalized_name, YGEdgeBottom) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Start, capitalized_name##Start, capitalized_name, YGEdgeStart) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##End, capitalized_name##End, capitalized_name, YGEdgeEnd) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Horizontal, capitalized_name##Horizontal, capitalized_name, YGEdgeHorizontal) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Vertical, capitalized_name##Vertical, capitalized_name, YGEdgeVertical) \
YG_VALUE_EDGE_PROPERTY(lowercased_name, capitalized_name, capitalized_name, YGEdgeAll)
YGValue YGPointValue(CGFloat value)
{
return (YGValue) { .value = value, .unit = YGUnitPoint };
}
YGValue YGPercentValue(CGFloat value)
{
return (YGValue) { .value = value, .unit = YGUnitPercent };
} }
static YGConfigRef globalConfig; static YGConfigRef globalConfig;
@interface YGLayout () @interface YGLayout ()
@property (nonatomic, weak, readonly) UIView *view; @property(nonatomic, weak, readonly) UIView* view;
@property(nonatomic, assign, readonly) BOOL isUIView; @property(nonatomic, assign, readonly) BOOL isUIView;
@end @end
@implementation YGLayout @implementation YGLayout
@synthesize isEnabled=_isEnabled; @synthesize isEnabled = _isEnabled;
@synthesize isIncludedInLayout=_isIncludedInLayout; @synthesize isIncludedInLayout = _isIncludedInLayout;
@synthesize node=_node; @synthesize node = _node;
+ (void)initialize + (void)initialize {
{
globalConfig = YGConfigNew(); globalConfig = YGConfigNew();
YGConfigSetExperimentalFeatureEnabled(globalConfig, YGExperimentalFeatureWebFlexBasis, true); YGConfigSetExperimentalFeatureEnabled(
globalConfig, YGExperimentalFeatureWebFlexBasis, true);
YGConfigSetPointScaleFactor(globalConfig, [UIScreen mainScreen].scale); YGConfigSetPointScaleFactor(globalConfig, [UIScreen mainScreen].scale);
} }
- (instancetype)initWithView:(UIView*)view - (instancetype)initWithView:(UIView*)view {
{
if (self = [super init]) { if (self = [super init]) {
_view = view; _view = view;
_node = YGNodeNewWithConfig(globalConfig); _node = YGNodeNewWithConfig(globalConfig);
YGNodeSetContext(_node, (__bridge void *) view); YGNodeSetContext(_node, (__bridge void*)view);
_isEnabled = NO; _isEnabled = NO;
_isIncludedInLayout = YES; _isIncludedInLayout = YES;
_isUIView = [view isMemberOfClass:[UIView class]]; _isUIView = [view isMemberOfClass:[UIView class]];
@@ -160,18 +191,15 @@ static YGConfigRef globalConfig;
return self; return self;
} }
- (void)dealloc - (void)dealloc {
{
YGNodeFree(self.node); YGNodeFree(self.node);
} }
- (BOOL)isDirty - (BOOL)isDirty {
{
return YGNodeIsDirty(self.node); return YGNodeIsDirty(self.node);
} }
- (void)markDirty - (void)markDirty {
{
if (self.isDirty || !self.isLeaf) { if (self.isDirty || !self.isLeaf) {
return; return;
} }
@@ -187,17 +215,17 @@ static YGConfigRef globalConfig;
YGNodeMarkDirty(node); YGNodeMarkDirty(node);
} }
- (NSUInteger)numberOfChildren - (NSUInteger)numberOfChildren {
{
return YGNodeGetChildCount(self.node); return YGNodeGetChildCount(self.node);
} }
- (BOOL)isLeaf - (BOOL)isLeaf {
{ NSAssert(
NSAssert([NSThread isMainThread], @"This method must be called on the main thread."); [NSThread isMainThread],
@"This method must be called on the main thread.");
if (self.isEnabled) { if (self.isEnabled) {
for (UIView *subview in self.view.subviews) { for (UIView* subview in self.view.subviews) {
YGLayout *const yoga = subview.yoga; YGLayout* const yoga = subview.yoga;
if (yoga.isEnabled && yoga.isIncludedInLayout) { if (yoga.isEnabled && yoga.isIncludedInLayout) {
return NO; return NO;
} }
@@ -209,13 +237,11 @@ static YGConfigRef globalConfig;
#pragma mark - Style #pragma mark - Style
- (YGPositionType)position - (YGPositionType)position {
{
return YGNodeStyleGetPositionType(self.node); return YGNodeStyleGetPositionType(self.node);
} }
- (void)setPosition:(YGPositionType)position - (void)setPosition:(YGPositionType)position {
{
YGNodeStyleSetPositionType(self.node, position); YGNodeStyleSetPositionType(self.node, position);
} }
@@ -261,25 +287,23 @@ YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
#pragma mark - Layout and Sizing #pragma mark - Layout and Sizing
- (YGDirection)resolvedDirection - (YGDirection)resolvedDirection {
{
return YGNodeLayoutGetDirection(self.node); return YGNodeLayoutGetDirection(self.node);
} }
- (void)applyLayout - (void)applyLayout {
{
[self calculateLayoutWithSize:self.view.bounds.size]; [self calculateLayoutWithSize:self.view.bounds.size];
YGApplyLayoutToViewHierarchy(self.view, NO); YGApplyLayoutToViewHierarchy(self.view, NO);
} }
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin - (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin {
{
[self calculateLayoutWithSize:self.view.bounds.size]; [self calculateLayoutWithSize:self.view.bounds.size];
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin); YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
} }
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin dimensionFlexibility:(YGDimensionFlexibility)dimensionFlexibility - (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
{ dimensionFlexibility:
(YGDimensionFlexibility)dimensionFlexibility {
CGSize size = self.view.bounds.size; CGSize size = self.view.bounds.size;
if (dimensionFlexibility & YGDimensionFlexibilityFlexibleWidth) { if (dimensionFlexibility & YGDimensionFlexibilityFlexibleWidth) {
size.width = YGUndefined; size.width = YGUndefined;
@@ -291,18 +315,15 @@ YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin); YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
} }
- (CGSize)intrinsicSize {
- (CGSize)intrinsicSize
{
const CGSize constrainedSize = { const CGSize constrainedSize = {
.width = YGUndefined, .width = YGUndefined,
.height = YGUndefined, .height = YGUndefined,
}; };
return [self calculateLayoutWithSize:constrainedSize]; return [self calculateLayoutWithSize:constrainedSize];
} }
- (CGSize)calculateLayoutWithSize:(CGSize)size - (CGSize)calculateLayoutWithSize:(CGSize)size {
{
NSAssert([NSThread isMainThread], @"Yoga calculation must be done on main."); NSAssert([NSThread isMainThread], @"Yoga calculation must be done on main.");
NSAssert(self.isEnabled, @"Yoga is not enabled for this view."); NSAssert(self.isEnabled, @"Yoga is not enabled for this view.");
@@ -310,30 +331,28 @@ YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
const YGNodeRef node = self.node; const YGNodeRef node = self.node;
YGNodeCalculateLayout( YGNodeCalculateLayout(
node, node, size.width, size.height, YGNodeStyleGetDirection(node));
size.width,
size.height,
YGNodeStyleGetDirection(node));
return (CGSize) { return (CGSize){
.width = YGNodeLayoutGetWidth(node), .width = YGNodeLayoutGetWidth(node),
.height = YGNodeLayoutGetHeight(node), .height = YGNodeLayoutGetHeight(node),
}; };
} }
#pragma mark - Private #pragma mark - Private
static YGSize YGMeasureView( static YGSize YGMeasureView(
YGNodeRef node, YGNodeRef node,
float width, float width,
YGMeasureMode widthMode, YGMeasureMode widthMode,
float height, float height,
YGMeasureMode heightMode) YGMeasureMode heightMode) {
{ const CGFloat constrainedWidth =
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width; (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height; const CGFloat constrainedHeight =
(heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : height;
UIView *view = (__bridge UIView*) YGNodeGetContext(node); UIView* view = (__bridge UIView*)YGNodeGetContext(node);
CGSize sizeThatFits = CGSizeZero; CGSize sizeThatFits = CGSizeZero;
// The default implementation of sizeThatFits: returns the existing size of // The default implementation of sizeThatFits: returns the existing size of
@@ -349,17 +368,18 @@ static YGSize YGMeasureView(
}]; }];
} }
return (YGSize) { return (YGSize){
.width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode), .width = YGSanitizeMeasurement(
.height = YGSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode), constrainedWidth, sizeThatFits.width, widthMode),
.height = YGSanitizeMeasurement(
constrainedHeight, sizeThatFits.height, heightMode),
}; };
} }
static CGFloat YGSanitizeMeasurement( static CGFloat YGSanitizeMeasurement(
CGFloat constrainedSize, CGFloat constrainedSize,
CGFloat measuredSize, CGFloat measuredSize,
YGMeasureMode measureMode) YGMeasureMode measureMode) {
{
CGFloat result; CGFloat result;
if (measureMode == YGMeasureModeExactly) { if (measureMode == YGMeasureModeExactly) {
result = constrainedSize; result = constrainedSize;
@@ -372,13 +392,14 @@ static CGFloat YGSanitizeMeasurement(
return result; return result;
} }
static BOOL YGNodeHasExactSameChildren(const YGNodeRef node, NSArray<UIView *> *subviews) static BOOL YGNodeHasExactSameChildren(
{ const YGNodeRef node,
NSArray<UIView*>* subviews) {
if (YGNodeGetChildCount(node) != subviews.count) { if (YGNodeGetChildCount(node) != subviews.count) {
return NO; return NO;
} }
for (int i=0; i<subviews.count; i++) { for (int i = 0; i < subviews.count; i++) {
if (YGNodeGetChild(node, i) != subviews[i].yoga.node) { if (YGNodeGetChild(node, i) != subviews[i].yoga.node) {
return NO; return NO;
} }
@@ -387,9 +408,8 @@ static BOOL YGNodeHasExactSameChildren(const YGNodeRef node, NSArray<UIView *> *
return YES; return YES;
} }
static void YGAttachNodesFromViewHierachy(UIView *const view) static void YGAttachNodesFromViewHierachy(UIView* const view) {
{ YGLayout* const yoga = view.yoga;
YGLayout *const yoga = view.yoga;
const YGNodeRef node = yoga.node; const YGNodeRef node = yoga.node;
// Only leaf nodes should have a measure function // Only leaf nodes should have a measure function
@@ -399,8 +419,9 @@ static void YGAttachNodesFromViewHierachy(UIView *const view)
} else { } else {
YGNodeSetMeasureFunc(node, NULL); YGNodeSetMeasureFunc(node, NULL);
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count]; NSMutableArray<UIView*>* subviewsToInclude =
for (UIView *subview in view.subviews) { [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
for (UIView* subview in view.subviews) {
if (subview.yoga.isEnabled && subview.yoga.isIncludedInLayout) { if (subview.yoga.isEnabled && subview.yoga.isIncludedInLayout) {
[subviewsToInclude addObject:subview]; [subviewsToInclude addObject:subview];
} }
@@ -408,19 +429,18 @@ static void YGAttachNodesFromViewHierachy(UIView *const view)
if (!YGNodeHasExactSameChildren(node, subviewsToInclude)) { if (!YGNodeHasExactSameChildren(node, subviewsToInclude)) {
YGRemoveAllChildren(node); YGRemoveAllChildren(node);
for (int i=0; i<subviewsToInclude.count; i++) { for (int i = 0; i < subviewsToInclude.count; i++) {
YGNodeInsertChild(node, subviewsToInclude[i].yoga.node, i); YGNodeInsertChild(node, subviewsToInclude[i].yoga.node, i);
} }
} }
for (UIView *const subview in subviewsToInclude) { for (UIView* const subview in subviewsToInclude) {
YGAttachNodesFromViewHierachy(subview); YGAttachNodesFromViewHierachy(subview);
} }
} }
} }
static void YGRemoveAllChildren(const YGNodeRef node) static void YGRemoveAllChildren(const YGNodeRef node) {
{
if (node == NULL) { if (node == NULL) {
return; return;
} }
@@ -428,22 +448,22 @@ static void YGRemoveAllChildren(const YGNodeRef node)
YGNodeRemoveAllChildren(node); YGNodeRemoveAllChildren(node);
} }
static CGFloat YGRoundPixelValue(CGFloat value) static CGFloat YGRoundPixelValue(CGFloat value) {
{
static CGFloat scale; static CGFloat scale;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^(){ dispatch_once(&onceToken, ^() {
scale = [UIScreen mainScreen].scale; scale = [UIScreen mainScreen].scale;
}); });
return roundf(value * scale) / scale; return roundf(value * scale) / scale;
} }
static void YGApplyLayoutToViewHierarchy(UIView *view, BOOL preserveOrigin) static void YGApplyLayoutToViewHierarchy(UIView* view, BOOL preserveOrigin) {
{ NSCAssert(
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread."); [NSThread isMainThread],
@"Framesetting should only be done on the main thread.");
const YGLayout *yoga = view.yoga; const YGLayout* yoga = view.yoga;
if (!yoga.isEnabled || !yoga.isIncludedInLayout) { if (!yoga.isEnabled || !yoga.isIncludedInLayout) {
return; return;
@@ -451,29 +471,33 @@ static void YGApplyLayoutToViewHierarchy(UIView *view, BOOL preserveOrigin)
YGNodeRef node = yoga.node; YGNodeRef node = yoga.node;
const CGPoint topLeft = { const CGPoint topLeft = {
YGNodeLayoutGetLeft(node), YGNodeLayoutGetLeft(node),
YGNodeLayoutGetTop(node), YGNodeLayoutGetTop(node),
}; };
const CGPoint bottomRight = { const CGPoint bottomRight = {
topLeft.x + YGNodeLayoutGetWidth(node), topLeft.x + YGNodeLayoutGetWidth(node),
topLeft.y + YGNodeLayoutGetHeight(node), topLeft.y + YGNodeLayoutGetHeight(node),
}; };
const CGPoint origin = preserveOrigin ? view.frame.origin : CGPointZero; const CGPoint origin = preserveOrigin ? view.frame.origin : CGPointZero;
view.frame = (CGRect) { view.frame = (CGRect){
.origin = { .origin =
.x = YGRoundPixelValue(topLeft.x + origin.x), {
.y = YGRoundPixelValue(topLeft.y + origin.y), .x = YGRoundPixelValue(topLeft.x + origin.x),
}, .y = YGRoundPixelValue(topLeft.y + origin.y),
.size = { },
.width = YGRoundPixelValue(bottomRight.x) - YGRoundPixelValue(topLeft.x), .size =
.height = YGRoundPixelValue(bottomRight.y) - YGRoundPixelValue(topLeft.y), {
}, .width = YGRoundPixelValue(bottomRight.x) -
YGRoundPixelValue(topLeft.x),
.height = YGRoundPixelValue(bottomRight.y) -
YGRoundPixelValue(topLeft.y),
},
}; };
if (!yoga.isLeaf) { if (!yoga.isLeaf) {
for (NSUInteger i=0; i<view.subviews.count; i++) { for (NSUInteger i = 0; i < view.subviews.count; i++) {
YGApplyLayoutToViewHierarchy(view.subviews[i], NO); YGApplyLayoutToViewHierarchy(view.subviews[i], NO);
} }
} }

View File

@@ -16,17 +16,15 @@
@implementation YogaKitTests @implementation YogaKitTests
- (void)testConfigureLayoutIsNoOpWithNilBlock - (void)testConfigureLayoutIsNoOpWithNilBlock {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
id block = nil; id block = nil;
XCTAssertNoThrow([view configureLayoutWithBlock:block]); XCTAssertNoThrow([view configureLayoutWithBlock:block]);
} }
- (void)testConfigureLayoutBlockWorksWithValidBlock - (void)testConfigureLayoutBlockWorksWithValidBlock {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; [view configureLayoutWithBlock:^(YGLayout* layout) {
[view configureLayoutWithBlock:^(YGLayout *layout){
XCTAssertNotNil(layout); XCTAssertNotNil(layout);
layout.isEnabled = YES; layout.isEnabled = YES;
layout.width = YGPointValue(25); layout.width = YGPointValue(25);
@@ -36,12 +34,11 @@
XCTAssertEqual(view.yoga.width.value, 25); XCTAssertEqual(view.yoga.width.value, 25);
} }
- (void)testNodesAreDeallocedWithSingleView - (void)testNodesAreDeallocedWithSingleView {
{ __weak YGLayout* layoutRef = nil;
__weak YGLayout *layoutRef = nil;
@autoreleasepool { @autoreleasepool {
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.flexBasis = YGPointValue(1); view.yoga.flexBasis = YGPointValue(1);
layoutRef = view.yoga; layoutRef = view.yoga;
@@ -53,17 +50,16 @@
XCTAssertNil(layoutRef); XCTAssertNil(layoutRef);
} }
- (void)testNodesAreDeallocedCascade - (void)testNodesAreDeallocedCascade {
{ __weak YGLayout* topLayout = nil;
__weak YGLayout *topLayout = nil; __weak YGLayout* subviewLayout = nil;
__weak YGLayout *subviewLayout = nil;
@autoreleasepool { @autoreleasepool {
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
topLayout = view.yoga; topLayout = view.yoga;
topLayout.flexBasis = YGPointValue(1); topLayout.flexBasis = YGPointValue(1);
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview = [[UIView alloc] initWithFrame:CGRectZero];
subviewLayout = subview.yoga; subviewLayout = subview.yoga;
subviewLayout.flexBasis = YGPointValue(1); subviewLayout.flexBasis = YGPointValue(1);
@@ -74,9 +70,8 @@
XCTAssertNil(subviewLayout); XCTAssertNil(subviewLayout);
} }
- (void)testIsEnabled - (void)testIsEnabled {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
XCTAssertFalse(view.yoga.isEnabled); XCTAssertFalse(view.yoga.isEnabled);
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
@@ -86,30 +81,31 @@
XCTAssertFalse(view.yoga.isEnabled); XCTAssertFalse(view.yoga.isEnabled);
} }
- (void)testSizeThatFitsAsserts - (void)testSizeThatFitsAsserts {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; dispatch_sync(
dispatch_sync(dispatch_queue_create("com.facebook.Yoga.testing", DISPATCH_QUEUE_SERIAL), ^(void){ dispatch_queue_create("com.facebook.Yoga.testing", DISPATCH_QUEUE_SERIAL),
XCTAssertThrows(view.yoga.intrinsicSize); ^(void) {
}); XCTAssertThrows(view.yoga.intrinsicSize);
});
} }
- (void)testSizeThatFitsSmoke - (void)testSizeThatFitsSmoke {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectZero];
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
container.yoga.alignItems = YGAlignFlexStart; container.yoga.alignItems = YGAlignFlexStart;
UILabel *longTextLabel = [[UILabel alloc] initWithFrame:CGRectZero]; UILabel* longTextLabel = [[UILabel alloc] initWithFrame:CGRectZero];
longTextLabel.text = @"This is a very very very very very very very very long piece of text."; longTextLabel.text =
@"This is a very very very very very very very very long piece of text.";
longTextLabel.lineBreakMode = NSLineBreakByTruncatingTail; longTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
longTextLabel.numberOfLines = 1; longTextLabel.numberOfLines = 1;
longTextLabel.yoga.isEnabled = YES; longTextLabel.yoga.isEnabled = YES;
longTextLabel.yoga.flexShrink = 1; longTextLabel.yoga.flexShrink = 1;
[container addSubview:longTextLabel]; [container addSubview:longTextLabel];
UIView *textBadgeView = [[UIView alloc] initWithFrame:CGRectZero]; UIView* textBadgeView = [[UIView alloc] initWithFrame:CGRectZero];
textBadgeView.yoga.isEnabled = YES; textBadgeView.yoga.isEnabled = YES;
textBadgeView.yoga.margin = YGPointValue(0); textBadgeView.yoga.margin = YGPointValue(0);
textBadgeView.yoga.width = YGPointValue(10); textBadgeView.yoga.width = YGPointValue(10);
@@ -124,7 +120,9 @@
const CGSize longTextLabelSize = longTextLabel.yoga.intrinsicSize; const CGSize longTextLabelSize = longTextLabel.yoga.intrinsicSize;
XCTAssertEqual(longTextLabelSize.height, containerSize.height); XCTAssertEqual(longTextLabelSize.height, containerSize.height);
XCTAssertEqual(longTextLabelSize.width + textBadgeView.yoga.intrinsicSize.width, containerSize.width); XCTAssertEqual(
longTextLabelSize.width + textBadgeView.yoga.intrinsicSize.width,
containerSize.width);
} }
- (void)testSizeThatFitsEmptyView { - (void)testSizeThatFitsEmptyView {
@@ -136,18 +134,17 @@
XCTAssertEqual(viewSize.width, 0); XCTAssertEqual(viewSize.width, 0);
} }
- (void)testPreservingOrigin - (void)testPreservingOrigin {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 75)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,75)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
view.yoga.flexBasis = YGPointValue(0); view.yoga.flexBasis = YGPointValue(0);
view.yoga.flexGrow = 1; view.yoga.flexGrow = 1;
[container addSubview:view]; [container addSubview:view];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* view2 = [[UIView alloc] initWithFrame:CGRectZero];
view2.yoga.isEnabled = YES; view2.yoga.isEnabled = YES;
view2.yoga.marginTop = YGPointValue(25); view2.yoga.marginTop = YGPointValue(25);
view2.yoga.flexBasis = YGPointValue(0); view2.yoga.flexBasis = YGPointValue(0);
@@ -161,28 +158,28 @@
XCTAssertEqual(25, view2.frame.origin.y); XCTAssertEqual(25, view2.frame.origin.y);
} }
- (void)testContainerWithFlexibleWidthGetsCorrectlySized - (void)testContainerWithFlexibleWidthGetsCorrectlySized {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
view.yoga.width = YGPointValue(100); view.yoga.width = YGPointValue(100);
view.yoga.height = YGPointValue(100); view.yoga.height = YGPointValue(100);
[container addSubview:view]; [container addSubview:view];
[container.yoga applyLayoutPreservingOrigin:YES dimensionFlexibility:YGDimensionFlexibilityFlexibleWidth]; [container.yoga
applyLayoutPreservingOrigin:YES
dimensionFlexibility:YGDimensionFlexibilityFlexibleWidth];
XCTAssertEqual(100, container.frame.size.width); XCTAssertEqual(100, container.frame.size.width);
XCTAssertEqual(200, container.frame.size.height); XCTAssertEqual(200, container.frame.size.height);
} }
- (void)testContainerWithFlexibleHeightGetsCorrectlySized - (void)testContainerWithFlexibleHeightGetsCorrectlySized {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
view.yoga.width = YGPointValue(100); view.yoga.width = YGPointValue(100);
view.yoga.height = YGPointValue(100); view.yoga.height = YGPointValue(100);
@@ -195,12 +192,11 @@
XCTAssertEqual(100, container.frame.size.height); XCTAssertEqual(100, container.frame.size.height);
} }
- (void)testContainerWithFlexibleWidthAndHeightGetsCorrectlySized - (void)testContainerWithFlexibleWidthAndHeightGetsCorrectlySized {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
view.yoga.width = YGPointValue(100); view.yoga.width = YGPointValue(100);
view.yoga.height = YGPointValue(100); view.yoga.height = YGPointValue(100);
@@ -214,12 +210,11 @@
XCTAssertEqual(100, container.frame.size.height); XCTAssertEqual(100, container.frame.size.height);
} }
- (void)testMarkingDirtyOnlyWorksOnLeafNodes - (void)testMarkingDirtyOnlyWorksOnLeafNodes {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectZero];
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview = [[UIView alloc] initWithFrame:CGRectZero];
subview.yoga.isEnabled = YES; subview.yoga.isEnabled = YES;
[container addSubview:subview]; [container addSubview:subview];
@@ -232,14 +227,13 @@
XCTAssertTrue(subview.yoga.isDirty); XCTAssertTrue(subview.yoga.isDirty);
} }
- (void)testThatMarkingLeafsAsDirtyWillTriggerASizeRecalculation - (void)testThatMarkingLeafsAsDirtyWillTriggerASizeRecalculation {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 50)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 50)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
container.yoga.alignItems = YGAlignFlexStart; container.yoga.alignItems = YGAlignFlexStart;
UILabel *view = [[UILabel alloc] initWithFrame:CGRectZero]; UILabel* view = [[UILabel alloc] initWithFrame:CGRectZero];
view.text = @"This is a short text."; view.text = @"This is a short text.";
view.numberOfLines = 1; view.numberOfLines = 1;
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
@@ -257,61 +251,70 @@
XCTAssertFalse(CGSizeEqualToSize(view.frame.size, viewSizeAfterFirstPass)); XCTAssertFalse(CGSizeEqualToSize(view.frame.size, viewSizeAfterFirstPass));
} }
- (void)testFrameAndOriginPlacement - (void)testFrameAndOriginPlacement {
{
const CGSize containerSize = CGSizeMake(320, 50); const CGSize containerSize = CGSizeMake(320, 50);
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)]; UIView* container = [[UIView alloc]
initWithFrame:CGRectMake(
0, 0, containerSize.width, containerSize.height)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1; subview1.yoga.flexGrow = 1;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1; subview2.yoga.flexGrow = 1;
[container addSubview:subview2]; [container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES; subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1; subview3.yoga.flexGrow = 1;
[container addSubview:subview3]; [container addSubview:subview3];
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertEqualWithAccuracy(subview2.frame.origin.x, CGRectGetMaxX(subview1.frame), FLT_EPSILON); XCTAssertEqualWithAccuracy(
XCTAssertEqualWithAccuracy(subview3.frame.origin.x, CGRectGetMaxX(subview2.frame), FLT_EPSILON); subview2.frame.origin.x, CGRectGetMaxX(subview1.frame), FLT_EPSILON);
XCTAssertEqualWithAccuracy(
subview3.frame.origin.x, CGRectGetMaxX(subview2.frame), FLT_EPSILON);
CGFloat totalWidth = 0; CGFloat totalWidth = 0;
for (UIView *view in container.subviews) { for (UIView* view in container.subviews) {
totalWidth += view.bounds.size.width; totalWidth += view.bounds.size.width;
} }
XCTAssertEqual(containerSize.width, totalWidth, @"The container's width is %.6f, the subviews take up %.6f", containerSize.width, totalWidth); XCTAssertEqual(
containerSize.width,
totalWidth,
@"The container's width is %.6f, the subviews take up %.6f",
containerSize.width,
totalWidth);
} }
- (void)testThatLayoutIsCorrectWhenWeSwapViewOrder - (void)testThatLayoutIsCorrectWhenWeSwapViewOrder {
{
const CGSize containerSize = CGSizeMake(300, 50); const CGSize containerSize = CGSizeMake(300, 50);
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)]; UIView* container = [[UIView alloc]
initWithFrame:CGRectMake(
0, 0, containerSize.width, containerSize.height)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1; subview1.yoga.flexGrow = 1;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1; subview2.yoga.flexGrow = 1;
[container addSubview:subview2]; [container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES; subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1; subview3.yoga.flexGrow = 1;
[container addSubview:subview3]; [container addSubview:subview3];
@@ -333,32 +336,33 @@
XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50))); XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50)));
} }
- (void)testThatWeRespectIncludeInLayoutFlag - (void)testThatWeRespectIncludeInLayoutFlag {
{
const CGSize containerSize = CGSizeMake(300, 50); const CGSize containerSize = CGSizeMake(300, 50);
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)]; UIView* container = [[UIView alloc]
initWithFrame:CGRectMake(
0, 0, containerSize.width, containerSize.height)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1; subview1.yoga.flexGrow = 1;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1; subview2.yoga.flexGrow = 1;
[container addSubview:subview2]; [container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES; subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1; subview3.yoga.flexGrow = 1;
[container addSubview:subview3]; [container addSubview:subview3];
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
for (UIView *subview in container.subviews) { for (UIView* subview in container.subviews) {
XCTAssertEqual(subview.bounds.size.width, 100); XCTAssertEqual(subview.bounds.size.width, 100);
} }
@@ -368,27 +372,27 @@
XCTAssertEqual(subview1.bounds.size.width, 150); XCTAssertEqual(subview1.bounds.size.width, 150);
XCTAssertEqual(subview2.bounds.size.width, 150); XCTAssertEqual(subview2.bounds.size.width, 150);
// We don't set the frame to zero, so, it should be set to what it was previously at. // We don't set the frame to zero, so, it should be set to what it was
// previously at.
XCTAssertEqual(subview3.bounds.size.width, 100); XCTAssertEqual(subview3.bounds.size.width, 100);
} }
- (void)testThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews - (void)testThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectZero];
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.isIncludedInLayout = NO; subview1.yoga.isIncludedInLayout = NO;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.isIncludedInLayout = NO; subview2.yoga.isIncludedInLayout = NO;
[container addSubview:subview2]; [container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES; subview3.yoga.isEnabled = YES;
subview3.yoga.isIncludedInLayout = YES; subview3.yoga.isIncludedInLayout = YES;
[container addSubview:subview3]; [container addSubview:subview3];
@@ -401,23 +405,22 @@
XCTAssertEqual(container.yoga.numberOfChildren, 2); XCTAssertEqual(container.yoga.numberOfChildren, 2);
} }
- (void)testThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond - (void)testThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1; subview1.yoga.flexGrow = 1;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1; subview2.yoga.flexGrow = 1;
[container addSubview:subview2]; [container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES; subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1; subview3.yoga.flexGrow = 1;
subview3.yoga.isIncludedInLayout = NO; subview3.yoga.isIncludedInLayout = NO;
@@ -437,13 +440,12 @@
XCTAssertEqual(subview3.bounds.size.width, 100); XCTAssertEqual(subview3.bounds.size.width, 100);
} }
- (void)testIsLeafFlag - (void)testIsLeafFlag {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
XCTAssertTrue(view.yoga.isLeaf); XCTAssertTrue(view.yoga.isLeaf);
for (int i=0; i<10; i++) { for (int i = 0; i < 10; i++) {
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview = [[UIView alloc] initWithFrame:CGRectZero];
[view addSubview:subview]; [view addSubview:subview];
} }
XCTAssertTrue(view.yoga.isLeaf); XCTAssertTrue(view.yoga.isLeaf);
@@ -452,99 +454,95 @@
view.yoga.width = YGPointValue(50); view.yoga.width = YGPointValue(50);
XCTAssertTrue(view.yoga.isLeaf); XCTAssertTrue(view.yoga.isLeaf);
UIView *const subview = view.subviews[0]; UIView* const subview = view.subviews[0];
subview.yoga.isEnabled = YES; subview.yoga.isEnabled = YES;
subview.yoga.width = YGPointValue(50); subview.yoga.width = YGPointValue(50);
XCTAssertFalse(view.yoga.isLeaf); XCTAssertFalse(view.yoga.isLeaf);
} }
- (void)testThatWeCorrectlyAttachNestedViews - (void)testThatWeCorrectlyAttachNestedViews {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)]; container.yoga.isEnabled = YES;
container.yoga.isEnabled = YES; container.yoga.flexDirection = YGFlexDirectionColumn;
container.yoga.flexDirection = YGFlexDirectionColumn;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.width = YGPointValue(100); subview1.yoga.width = YGPointValue(100);
subview1.yoga.flexGrow = 1; subview1.yoga.flexGrow = 1;
subview1.yoga.flexDirection = YGFlexDirectionColumn; subview1.yoga.flexDirection = YGFlexDirectionColumn;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.width = YGPointValue(150); subview2.yoga.width = YGPointValue(150);
subview2.yoga.flexGrow = 1; subview2.yoga.flexGrow = 1;
subview2.yoga.flexDirection = YGFlexDirectionColumn; subview2.yoga.flexDirection = YGFlexDirectionColumn;
[container addSubview:subview2]; [container addSubview:subview2];
for (UIView *view in @[subview1, subview2]) { for (UIView* view in @[ subview1, subview2 ]) {
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero]; UIView* someView = [[UIView alloc] initWithFrame:CGRectZero];
someView.yoga.isEnabled = YES; someView.yoga.isEnabled = YES;
someView.yoga.flexGrow = 1; someView.yoga.flexGrow = 1;
[view addSubview:someView]; [view addSubview:someView];
} }
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
// Add the same amount of new views, reapply layout. // Add the same amount of new views, reapply layout.
for (UIView *view in @[subview1, subview2]) { for (UIView* view in @[ subview1, subview2 ]) {
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero]; UIView* someView = [[UIView alloc] initWithFrame:CGRectZero];
someView.yoga.isEnabled = YES; someView.yoga.isEnabled = YES;
someView.yoga.flexGrow = 1; someView.yoga.flexGrow = 1;
[view addSubview:someView]; [view addSubview:someView];
} }
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertEqual(subview1.bounds.size.width, 100); XCTAssertEqual(subview1.bounds.size.width, 100);
XCTAssertEqual(subview1.bounds.size.height, 25); XCTAssertEqual(subview1.bounds.size.height, 25);
for (UIView *subview in subview1.subviews) { for (UIView* subview in subview1.subviews) {
const CGSize subviewSize = subview.bounds.size; const CGSize subviewSize = subview.bounds.size;
XCTAssertNotEqual(subviewSize.width, 0); XCTAssertNotEqual(subviewSize.width, 0);
XCTAssertNotEqual(subviewSize.height, 0); XCTAssertNotEqual(subviewSize.height, 0);
XCTAssertFalse(isnan(subviewSize.height)); XCTAssertFalse(isnan(subviewSize.height));
XCTAssertFalse(isnan(subviewSize.width)); XCTAssertFalse(isnan(subviewSize.width));
} }
XCTAssertEqual(subview2.bounds.size.width, 150); XCTAssertEqual(subview2.bounds.size.width, 150);
XCTAssertEqual(subview2.bounds.size.height, 25); XCTAssertEqual(subview2.bounds.size.height, 25);
for (UIView *subview in subview2.subviews) { for (UIView* subview in subview2.subviews) {
const CGSize subviewSize = subview.bounds.size; const CGSize subviewSize = subview.bounds.size;
XCTAssertNotEqual(subviewSize.width, 0); XCTAssertNotEqual(subviewSize.width, 0);
XCTAssertNotEqual(subviewSize.height, 0); XCTAssertNotEqual(subviewSize.height, 0);
XCTAssertFalse(isnan(subviewSize.height)); XCTAssertFalse(isnan(subviewSize.height));
XCTAssertFalse(isnan(subviewSize.width)); XCTAssertFalse(isnan(subviewSize.width));
} }
} }
- (void)testThatANonLeafNodeCanBecomeALeafNode - (void)testThatANonLeafNodeCanBecomeALeafNode {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)]; container.yoga.isEnabled = YES;
container.yoga.isEnabled = YES;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
[subview1 addSubview:subview2]; [subview1 addSubview:subview2];
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
[subview2 removeFromSuperview]; [subview2 removeFromSuperview];
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
} }
- (void)testPointPercent - (void)testPointPercent {
{
XCTAssertEqual(YGPointValue(1).value, 1); XCTAssertEqual(YGPointValue(1).value, 1);
XCTAssertEqual(YGPointValue(1).unit, YGUnitPoint); XCTAssertEqual(YGPointValue(1).unit, YGUnitPoint);
XCTAssertEqual(YGPercentValue(2).value, 2); XCTAssertEqual(YGPercentValue(2).value, 2);
XCTAssertEqual(YGPercentValue(2).unit, YGUnitPercent); XCTAssertEqual(YGPercentValue(2).unit, YGUnitPercent);
} }
- (void)testPositionalPropertiesWork - (void)testPositionalPropertiesWork {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.left = YGPointValue(1); view.yoga.left = YGPointValue(1);
XCTAssertEqual(view.yoga.left.value, 1); XCTAssertEqual(view.yoga.left.value, 1);
@@ -589,9 +587,8 @@
XCTAssertEqual(view.yoga.end.unit, YGUnitPercent); XCTAssertEqual(view.yoga.end.unit, YGUnitPercent);
} }
- (void)testMarginPropertiesWork - (void)testMarginPropertiesWork {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.margin = YGPointValue(1); view.yoga.margin = YGPointValue(1);
XCTAssertEqual(view.yoga.margin.value, 1); XCTAssertEqual(view.yoga.margin.value, 1);
@@ -657,9 +654,8 @@
XCTAssertEqual(view.yoga.marginEnd.unit, YGUnitPercent); XCTAssertEqual(view.yoga.marginEnd.unit, YGUnitPercent);
} }
- (void)testPaddingPropertiesWork - (void)testPaddingPropertiesWork {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.padding = YGPointValue(1); view.yoga.padding = YGPointValue(1);
XCTAssertEqual(view.yoga.padding.value, 1); XCTAssertEqual(view.yoga.padding.value, 1);
@@ -725,9 +721,8 @@
XCTAssertEqual(view.yoga.paddingEnd.unit, YGUnitPercent); XCTAssertEqual(view.yoga.paddingEnd.unit, YGUnitPercent);
} }
- (void)testBorderWidthPropertiesWork - (void)testBorderWidthPropertiesWork {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.borderWidth = 1; view.yoga.borderWidth = 1;
XCTAssertEqual(view.yoga.borderWidth, 1); XCTAssertEqual(view.yoga.borderWidth, 1);

View File

@@ -11,45 +11,41 @@
@implementation ViewController @implementation ViewController
- (void)viewDidLoad - (void)viewDidLoad {
{ UIView* root = self.view;
UIView *root = self.view; root.backgroundColor = [UIColor redColor];
root.backgroundColor = [UIColor redColor]; root.yoga.isEnabled = YES;
root.yoga.isEnabled = YES; root.yoga.width = YGPointValue(self.view.bounds.size.width);
root.yoga.width = YGPointValue(self.view.bounds.size.width); root.yoga.height = YGPointValue(self.view.bounds.size.height);
root.yoga.height = YGPointValue(self.view.bounds.size.height); root.yoga.alignItems = YGAlignCenter;
root.yoga.alignItems = YGAlignCenter; root.yoga.justifyContent = YGJustifyCenter;
root.yoga.justifyContent = YGJustifyCenter;
UIView *child1 = [UIView new]; UIView* child1 = [UIView new];
child1.backgroundColor = [UIColor blueColor]; child1.backgroundColor = [UIColor blueColor];
child1.yoga.isEnabled = YES; child1.yoga.isEnabled = YES;
child1.yoga.width = YGPointValue(100); child1.yoga.width = YGPointValue(100);
child1.yoga.height = YGPointValue(100); child1.yoga.height = YGPointValue(100);
UIView *child2 = [UIView new]; UIView* child2 = [UIView new];
child2.backgroundColor = [UIColor greenColor]; child2.backgroundColor = [UIColor greenColor];
child2.frame = (CGRect) { child2.frame = (CGRect){
.size = { .size = {
.width = 200, .width = 200,
.height = 100, .height = 100,
} }};
};
UIView *child3 = [UIView new]; UIView* child3 = [UIView new];
child3.backgroundColor = [UIColor yellowColor]; child3.backgroundColor = [UIColor yellowColor];
child3.frame = (CGRect) { child3.frame = (CGRect){
.size = { .size = {
.width = 100, .width = 100,
.height = 100, .height = 100,
} }};
};
[child2 addSubview:child3]; [child2 addSubview:child3];
[root addSubview:child1]; [root addSubview:child1];
[root addSubview:child2]; [root addSubview:child2];
[root.yoga applyLayoutPreservingOrigin:NO]; [root.yoga applyLayoutPreservingOrigin:NO];
} }
@end @end

View File

@@ -3,10 +3,11 @@
# This source code is licensed under the MIT license found in the # This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree. # LICENSE file in the root directory of this source tree.
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_RES_TARGET", "JAVA_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "yoga_android_aar", "yoga_android_resource") load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_RES_TARGET", "JAVA_TARGET", "PROGUARD_ANNOTATIONS_TARGET", "yoga_android_aar", "yoga_android_resource")
yoga_android_aar( yoga_android_aar(
name = "android", name = "android",
enable_relinker = True,
manifest_skeleton = "src/main/AndroidManifest.xml", manifest_skeleton = "src/main/AndroidManifest.xml",
visibility = [ visibility = [
"PUBLIC", "PUBLIC",
@@ -15,7 +16,7 @@ yoga_android_aar(
ANDROID_JAVA_TARGET, ANDROID_JAVA_TARGET,
ANDROID_RES_TARGET, ANDROID_RES_TARGET,
JAVA_TARGET, JAVA_TARGET,
PROGRUARD_ANNOTATIONS_TARGET, PROGUARD_ANNOTATIONS_TARGET,
], ],
) )

View File

@@ -5,17 +5,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
apply plugin: 'com.jfrog.bintray'
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'maven-publish'
version = VERSION_NAME
group = GROUP
android { android {
compileSdkVersion rootProject.compileSdkVersion compileSdkVersion rootProject.compileSdkVersion
buildToolsVersion rootProject.buildToolsVersion buildToolsVersion rootProject.buildToolsVersion
ndkVersion rootProject.ndkVersion
defaultConfig { defaultConfig {
minSdkVersion rootProject.minSdkVersion minSdkVersion rootProject.minSdkVersion
@@ -32,21 +27,10 @@ dependencies {
api project(':yoga') api project(':yoga')
} }
task sourcesJar(type: Jar) { // We don't build Javadoc at this time as we can't disable "BUCK" files
classifier = 'source' // from mistakenly getting parsed as Java.
from android.sourceSets.main.java.srcDirs tasks.withType(Javadoc).all {
enabled = false
} }
task javadoc(type: Javadoc) { apply plugin: 'com.vanniktech.maven.publish'
failOnError false
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
apply from: rootProject.file('gradle/release.gradle')

View File

@@ -8,6 +8,7 @@ load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_SAM
yoga_android_library( yoga_android_library(
name = "yoga", name = "yoga",
srcs = glob(["**/*.java"]), srcs = glob(["**/*.java"]),
autoglob = False,
visibility = [ visibility = [
"PUBLIC", "PUBLIC",
], ],

View File

@@ -8,6 +8,7 @@ load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_RES_TARGET", "INFER_ANNOTA
yoga_android_library( yoga_android_library(
name = "android", name = "android",
srcs = glob(["**/*.java"]), srcs = glob(["**/*.java"]),
autoglob = False,
visibility = [ visibility = [
"PUBLIC", "PUBLIC",
], ],

View File

@@ -10,14 +10,11 @@
buildscript { buildscript {
repositories { repositories {
google() google()
jcenter() mavenCentral()
maven { url 'https://maven.google.com/' }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.0' classpath 'com.android.tools.build:gradle:4.2.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' classpath 'com.vanniktech:gradle-maven-publish-plugin:0.15.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }
@@ -26,15 +23,16 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
google() google()
jcenter() mavenCentral()
} }
} }
ext { ext {
minSdkVersion = 14 minSdkVersion = 14
targetSdkVersion = 25 targetSdkVersion = 29
compileSdkVersion = 26 compileSdkVersion = 29
buildToolsVersion = '28.0.3' buildToolsVersion = '30.0.2'
ndkVersion = '21.3.6528147'
sourceCompatibilityVersion = JavaVersion.VERSION_1_7 sourceCompatibilityVersion = JavaVersion.VERSION_1_7
targetCompatibilityVersion = JavaVersion.VERSION_1_7 targetCompatibilityVersion = JavaVersion.VERSION_1_7
} }

View File

@@ -9,11 +9,12 @@
static YGInteropLogger gManagedLogger; static YGInteropLogger gManagedLogger;
static int unmanagedLogger(const YGConfigRef config, static int unmanagedLogger(
const YGNodeRef node, const YGConfigRef config,
YGLogLevel level, const YGNodeRef node,
const char *format, YGLogLevel level,
va_list args) { const char* format,
va_list args) {
int result = 0; int result = 0;
if (gManagedLogger) { if (gManagedLogger) {
char message[8192]; char message[8192];

View File

@@ -11,10 +11,11 @@
YG_EXTERN_C_BEGIN YG_EXTERN_C_BEGIN
typedef int (*YGInteropLogger)(const void *unmanagedConfigPtr, typedef int (*YGInteropLogger)(
const void *unmanagedNodePtr, const void* unmanagedConfigPtr,
YGLogLevel level, const void* unmanagedNodePtr,
const char *message); YGLogLevel level,
const char* message);
WIN_EXPORT YGConfigRef YGConfigGetDefault(); WIN_EXPORT YGConfigRef YGConfigGetDefault();

View File

@@ -36,7 +36,7 @@
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
@@ -48,7 +48,7 @@
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
@@ -62,13 +62,13 @@
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
@@ -227,6 +227,8 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\yoga\event\event.h" />
<ClInclude Include="..\..\yoga\log.h" />
<ClInclude Include="..\..\yoga\Utils.h" /> <ClInclude Include="..\..\yoga\Utils.h" />
<ClInclude Include="..\..\yoga\YGConfig.h" /> <ClInclude Include="..\..\yoga\YGConfig.h" />
<ClInclude Include="..\..\yoga\YGEnums.h" /> <ClInclude Include="..\..\yoga\YGEnums.h" />
@@ -236,6 +238,7 @@
<ClInclude Include="..\..\yoga\YGNode.h" /> <ClInclude Include="..\..\yoga\YGNode.h" />
<ClInclude Include="..\..\yoga\YGNodePrint.h" /> <ClInclude Include="..\..\yoga\YGNodePrint.h" />
<ClInclude Include="..\..\yoga\YGStyle.h" /> <ClInclude Include="..\..\yoga\YGStyle.h" />
<ClInclude Include="..\..\yoga\YGValue.h" />
<ClInclude Include="..\..\yoga\Yoga-internal.h" /> <ClInclude Include="..\..\yoga\Yoga-internal.h" />
<ClInclude Include="..\..\yoga\Yoga.h" /> <ClInclude Include="..\..\yoga\Yoga.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
@@ -243,14 +246,16 @@
<ClInclude Include="targetver.h" /> <ClInclude Include="targetver.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\yoga\event\event.cpp" />
<ClCompile Include="..\..\yoga\log.cpp" />
<ClCompile Include="..\..\yoga\Utils.cpp" /> <ClCompile Include="..\..\yoga\Utils.cpp" />
<ClCompile Include="..\..\yoga\YGConfig.cpp" /> <ClCompile Include="..\..\yoga\YGConfig.cpp" />
<ClCompile Include="..\..\yoga\YGEnums.cpp" /> <ClCompile Include="..\..\yoga\YGEnums.cpp" />
<ClCompile Include="..\..\yoga\YGFloatOptional.cpp" />
<ClCompile Include="..\..\yoga\YGLayout.cpp" /> <ClCompile Include="..\..\yoga\YGLayout.cpp" />
<ClCompile Include="..\..\yoga\YGNode.cpp" /> <ClCompile Include="..\..\yoga\YGNode.cpp" />
<ClCompile Include="..\..\yoga\YGNodePrint.cpp" /> <ClCompile Include="..\..\yoga\YGNodePrint.cpp" />
<ClCompile Include="..\..\yoga\YGStyle.cpp" /> <ClCompile Include="..\..\yoga\YGStyle.cpp" />
<ClCompile Include="..\..\yoga\YGValue.cpp" />
<ClCompile Include="..\..\yoga\Yoga.cpp" /> <ClCompile Include="..\..\yoga\Yoga.cpp" />
<ClCompile Include="YGInterop.cpp" /> <ClCompile Include="YGInterop.cpp" />
<ClCompile Include="dllmain.cpp"> <ClCompile Include="dllmain.cpp">

View File

@@ -1,104 +1,119 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Source Files"> <Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter> </Filter>
<Filter Include="Header Files"> <Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter> </Filter>
<Filter Include="Resource Files"> <Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="stdafx.h"> <ClInclude Include="stdafx.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="targetver.h"> <ClInclude Include="targetver.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="resource.h"> <ClInclude Include="resource.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\Utils.h"> <ClInclude Include="..\..\yoga\Utils.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\YGEnums.h"> <ClInclude Include="..\..\yoga\YGEnums.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\YGFloatOptional.h"> <ClInclude Include="..\..\yoga\YGFloatOptional.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\YGLayout.h"> <ClInclude Include="..\..\yoga\YGLayout.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\YGMacros.h"> <ClInclude Include="..\..\yoga\YGMacros.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\YGNode.h"> <ClInclude Include="..\..\yoga\YGNode.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\YGNodePrint.h"> <ClInclude Include="..\..\yoga\YGNodePrint.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\YGStyle.h"> <ClInclude Include="..\..\yoga\YGStyle.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\Yoga.h"> <ClInclude Include="..\..\yoga\Yoga.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\Yoga-internal.h"> <ClInclude Include="..\..\yoga\Yoga-internal.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\yoga\YGConfig.h"> <ClInclude Include="..\..\yoga\YGConfig.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
</ItemGroup> <ClInclude Include="..\..\yoga\YGValue.h">
<ItemGroup> <Filter>Header Files</Filter>
<ClCompile Include="stdafx.cpp"> </ClInclude>
<Filter>Source Files</Filter> <ClInclude Include="..\..\yoga\log.h">
</ClCompile> <Filter>Header Files</Filter>
<ClCompile Include="dllmain.cpp"> </ClInclude>
<Filter>Source Files</Filter> <ClInclude Include="..\..\yoga\event\event.h">
</ClCompile> <Filter>Header Files</Filter>
<ClCompile Include="YGInterop.cpp"> </ClInclude>
<Filter>Source Files</Filter> </ItemGroup>
</ClCompile> <ItemGroup>
<ClCompile Include="..\..\yoga\Utils.cpp"> <ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\yoga\YGEnums.cpp"> <ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\yoga\YGFloatOptional.cpp"> <ClCompile Include="YGInterop.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\yoga\YGLayout.cpp"> <ClCompile Include="..\..\yoga\Utils.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\yoga\YGNode.cpp"> <ClCompile Include="..\..\yoga\YGEnums.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\yoga\YGNodePrint.cpp"> <ClCompile Include="..\..\yoga\YGLayout.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\yoga\YGStyle.cpp"> <ClCompile Include="..\..\yoga\YGNode.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\yoga\Yoga.cpp"> <ClCompile Include="..\..\yoga\YGNodePrint.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\yoga\YGConfig.cpp"> <ClCompile Include="..\..\yoga\YGStyle.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
</ItemGroup> <ClCompile Include="..\..\yoga\Yoga.cpp">
<ItemGroup> <Filter>Source Files</Filter>
<ResourceCompile Include="Yoga.rc"> </ClCompile>
<Filter>Resource Files</Filter> <ClCompile Include="..\..\yoga\YGConfig.cpp">
</ResourceCompile> <Filter>Source Files</Filter>
</ItemGroup> </ClCompile>
<ClCompile Include="..\..\yoga\YGValue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\event\event.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\log.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Yoga.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project> </Project>

View File

@@ -8,7 +8,8 @@
// dllmain.cpp : Defines the entry point for the DLL application. // dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h" #include "stdafx.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { BOOL APIENTRY
DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) { switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:

View File

@@ -9,7 +9,8 @@
// Including SDKDDKVer.h defines the highest available Windows platform. // Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and // If you wish to build your application for a previous Windows platform,
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. // include WinSDKVer.h and set the _WIN32_WINNT macro to the platform you wish
// to support before including SDKDDKVer.h.
#include <SDKDDKVer.h> #include <SDKDDKVer.h>

View File

@@ -1,9 +1,10 @@
/** /*
* Copyright (c) Facebook, Inc. and its affiliates. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the LICENSE * This source code is licensed under the MIT license found in the
* file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// @Generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html // @Generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html
using System; using System;
@@ -333,5 +334,47 @@ namespace Facebook.Yoga
Assert.AreEqual(0f, root_child1.LayoutHeight); Assert.AreEqual(0f, root_child1.LayoutHeight);
} }
[Test]
public void Test_display_none_with_position_absolute()
{
YogaConfig config = new YogaConfig();
YogaNode root = new YogaNode(config);
root.Width = 100;
root.Height = 100;
YogaNode root_child0 = new YogaNode(config);
root_child0.PositionType = YogaPositionType.Absolute;
root_child0.Width = 100;
root_child0.Height = 100;
root_child0.Display = YogaDisplay.None;
root.Insert(0, root_child0);
root.StyleDirection = YogaDirection.LTR;
root.CalculateLayout();
Assert.AreEqual(0f, root.LayoutX);
Assert.AreEqual(0f, root.LayoutY);
Assert.AreEqual(100f, root.LayoutWidth);
Assert.AreEqual(100f, root.LayoutHeight);
Assert.AreEqual(0f, root_child0.LayoutX);
Assert.AreEqual(0f, root_child0.LayoutY);
Assert.AreEqual(0f, root_child0.LayoutWidth);
Assert.AreEqual(0f, root_child0.LayoutHeight);
root.StyleDirection = YogaDirection.RTL;
root.CalculateLayout();
Assert.AreEqual(0f, root.LayoutX);
Assert.AreEqual(0f, root.LayoutY);
Assert.AreEqual(100f, root.LayoutWidth);
Assert.AreEqual(100f, root.LayoutHeight);
Assert.AreEqual(0f, root_child0.LayoutX);
Assert.AreEqual(0f, root_child0.LayoutY);
Assert.AreEqual(0f, root_child0.LayoutWidth);
Assert.AreEqual(0f, root_child0.LayoutHeight);
}
} }
} }

View File

@@ -25,3 +25,7 @@
<div style="flex-grow: 1;"></div> <div style="flex-grow: 1;"></div>
<div style="flex-grow: 1; display:none; top: 10px;"></div> <div style="flex-grow: 1; display:none; top: 10px;"></div>
</div> </div>
<div id="display_none_with_position_absolute" style="width: 100px; height: 100px;">
<div style="display:none; position: absolute; width: 100px; height: 100px"></div>
</div>

View File

@@ -120,8 +120,9 @@ CSEmitter.prototype = Object.create(Emitter.prototype, {
YGOverflowHidden:{value:'YogaOverflow.Hidden'}, YGOverflowHidden:{value:'YogaOverflow.Hidden'},
YGOverflowVisible:{value:'YogaOverflow.Visible'}, YGOverflowVisible:{value:'YogaOverflow.Visible'},
YGPositionTypeAbsolute:{value:'YogaPositionType.Absolute'}, YGPositionTypeAbsolute:{value:'YogaPositionType.Static'},
YGPositionTypeRelative:{value:'YogaPositionType.Relative'}, YGPositionTypeRelative:{value:'YogaPositionType.Relative'},
YGPositionTypeAbsolute:{value:'YogaPositionType.Absolute'},
YGUndefined:{value:'YogaConstants.Undefined'}, YGUndefined:{value:'YogaConstants.Undefined'},

View File

@@ -41,11 +41,11 @@ function assert(condition, message) {
function printTest(e, LTRContainer, RTLContainer, genericContainer) { function printTest(e, LTRContainer, RTLContainer, genericContainer) {
e.push([ e.push([
'/**', '/*',
' * Copyright (c) Facebook, Inc. and its affiliates.', ' * Copyright (c) Facebook, Inc. and its affiliates.',
' *', ' *',
' * This source code is licensed under the MIT license found in the LICENSE', ' * This source code is licensed under the MIT license found in the',
' * file in the root directory of this source tree.', ' * LICENSE file in the root directory of this source tree.',
' */', ' */',
'// @Generated by gentest/gentest.rb from gentest/fixtures/' + document.title + '.html', '// @Generated by gentest/gentest.rb from gentest/fixtures/' + document.title + '.html',
'', '',

View File

@@ -7,13 +7,14 @@
require 'watir' require 'watir'
require 'fileutils' require 'fileutils'
caps = Selenium::WebDriver::Remote::Capabilities.chrome( browser = Watir::Browser.new(:chrome, "goog:loggingPrefs" => {
"loggingPrefs"=>{ "browser" => "ALL",
"browser"=>"ALL", "performance" => "ALL"
"performance"=>"ALL" },
} "chromeOptions" => {
) "w3c" => "false"
browser = Watir::Browser.new(:chrome, :desired_capabilities => caps, :switches => ['--force-device-scale-factor=1', '--window-position=0,0']) },
:switches => ['--force-device-scale-factor=1', '--window-position=0,0'])
Dir.chdir(File.dirname($0)) Dir.chdir(File.dirname($0))

View File

@@ -9,7 +9,7 @@
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
VERSION_NAME=1.16.0-SNAPSHOT VERSION_NAME=1.19.0
POM_URL=https://github.com/facebook/yoga POM_URL=https://github.com/facebook/yoga
POM_SCM_URL=https://github.com/facebook/yoga.git POM_SCM_URL=https://github.com/facebook/yoga.git
POM_SCM_CONNECTION=scm:git:https://github.com/facebook/yoga.git POM_SCM_CONNECTION=scm:git:https://github.com/facebook/yoga.git
@@ -17,5 +17,8 @@ POM_SCM_DEV_CONNECTION=scm:git:git@github.com:facebook/yoga.git
POM_LICENSE_NAME=MIT License POM_LICENSE_NAME=MIT License
POM_LICENSE_URL=https://github.com/facebook/yoga/blob/master/LICENSE POM_LICENSE_URL=https://github.com/facebook/yoga/blob/master/LICENSE
POM_LICENSE_DIST=repo POM_LICENSE_DIST=repo
POM_LICENCE_NAME=MIT License
POM_LICENCE_URL=https://github.com/facebook/yoga/blob/master/LICENSE
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=facebook POM_DEVELOPER_ID=facebook
POM_DEVELOPER_NAME=facebook POM_DEVELOPER_NAME=facebook

View File

@@ -1,44 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// Configure the Android maven publication
apply plugin: 'com.github.dcendents.android-maven'
version = VERSION_NAME
group = GROUP
// Set the .aar / .jar base file name to match the artifact ID
// in case the module has a different name
project.archivesBaseName = POM_ARTIFACT_ID
install {
repositories.mavenInstaller {
// This generates POM.xml with proper parameters
pom.project {
name POM_NAME
artifactId POM_ARTIFACT_ID
packaging POM_PACKAGING
description POM_DESCRIPTION
url projectUrl
scm {
url scmUrl
connection scmConnection
developerConnection scmDeveloperConnection
}
licenses projectLicenses
developers {
developer {
id developerId
name developerName
}
}
}
}
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// Android tasks for Javadoc and sources.jar generation
afterEvaluate { project ->
if (POM_PACKAGING == 'aar') {
task androidJavadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
exclude '**/pom.xml'
exclude '**/proguard_annotations.pro'
classpath += files(android.bootClasspath)
}
task androidJavadocJar(type: Jar) {
classifier = 'javadoc'
from androidJavadoc.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
android.libraryVariants.all { variant ->
def name = variant.name.capitalize()
task "jar${name}"(type: Jar, dependsOn: variant.javaCompile) {
from variant.javaCompile.destinationDir
}
}
artifacts.add('archives', androidJavadocJar)
artifacts.add('archives', androidSourcesJar)
}
if (POM_PACKAGING == 'jar') {
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
artifacts.add('archives', javadocJar)
artifacts.add('archives', sourcesJar)
}
}

View File

@@ -1,70 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// Upload to Bintray
apply plugin: 'com.jfrog.bintray'
def getBintrayUsername() {
return project.hasProperty('bintrayUsername') ? property('bintrayUsername') : System.getenv('BINTRAY_USERNAME')
}
def getBintrayApiKey() {
return project.hasProperty('bintrayApiKey') ? property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY')
}
def getBintrayGpgPassword() {
return project.hasProperty('bintrayGpgPassword') ? property('bintrayGpgPassword') : System.getenv('BINTRAY_GPG_PASSWORD')
}
def getMavenCentralUsername() {
return project.hasProperty('mavenCentralUsername') ? property('mavenCentralUsername') : System.getenv('MAVEN_CENTRAL_USERNAME')
}
def getMavenCentralPassword() {
return project.hasProperty('mavenCentralPassword') ? property('mavenCentralPassword') : System.getenv('MAVEN_CENTRAL_PASSWORD')
}
def shouldSyncWithMavenCentral() {
return project.hasProperty('syncWithMavenCentral') ? property('syncWithMavenCentral').toBoolean() : false
}
def dryRunOnly() {
return project.hasProperty('dryRun') ? property('dryRun').toBoolean() : false
}
bintray {
user = getBintrayUsername()
key = getBintrayApiKey()
configurations = ['archives']
pkg {
repo = bintrayRepo
userOrg = bintrayUserOrg
name = bintrayName
desc = bintrayDescription
websiteUrl = projectUrl
issueTrackerUrl = issuesUrl
vcsUrl = scmUrl
licenses = projectLicenses
dryRun = dryRunOnly()
override = true
publish = true
publicDownloadNumbers = true
version {
desc = bintrayDescription
gpg {
sign = true
passphrase = getBintrayGpgPassword()
}
mavenCentralSync {
sync = shouldSyncWithMavenCentral()
user = getMavenCentralUsername()
password = getMavenCentralPassword()
close = '1' // If set to 0, you have to manually click release
}
}
}
}

View File

@@ -1,96 +0,0 @@
/*
* Copyright 2013 Chris Banes
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
apply plugin: 'signing'
version = VERSION_NAME
group = GROUP
def isReleaseBuild() {
return VERSION_NAME.contains('SNAPSHOT') == false
}
def getReleaseRepositoryUrl() {
return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
: "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
}
def getSnapshotRepositoryUrl() {
return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
: "https://oss.sonatype.org/content/repositories/snapshots/"
}
def getRepositoryUsername() {
return hasProperty('SONATYPE_NEXUS_USERNAME') ? SONATYPE_NEXUS_USERNAME : ""
}
def getRepositoryPassword() {
return hasProperty('SONATYPE_NEXUS_PASSWORD') ? SONATYPE_NEXUS_PASSWORD : ""
}
afterEvaluate { project ->
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
pom.groupId = GROUP
pom.artifactId = POM_ARTIFACT_ID
pom.version = VERSION_NAME
repository(url: getReleaseRepositoryUrl()) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}
snapshotRepository(url: getSnapshotRepositoryUrl()) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}
pom.project {
name POM_NAME
packaging POM_PACKAGING
description POM_DESCRIPTION
url POM_URL
scm {
url POM_SCM_URL
connection POM_SCM_CONNECTION
developerConnection POM_SCM_DEV_CONNECTION
}
licenses {
license {
name POM_LICENSE_NAME
url POM_LICENSE_URL
distribution POM_LICENSE_DIST
}
}
developers {
developer {
id POM_DEVELOPER_ID
name POM_DEVELOPER_NAME
}
}
}
}
}
}
signing {
required { isReleaseBuild() && gradle.taskGraph.hasTask('uploadArchives') }
sign configurations.archives
}
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// Set up everything required for releasing on Bintray
ext {
bintrayRepo = 'maven'
bintrayUserOrg = 'facebook'
bintrayName = "${GROUP}:${POM_ARTIFACT_ID}"
bintrayDescription = POM_DESCRIPTION
projectUrl = POM_URL
issuesUrl = 'https://github.com/facebook/yoga/issues'
scmUrl = POM_SCM_URL
scmConnection = POM_SCM_CONNECTION
scmDeveloperConnection = POM_SCM_DEV_CONNECTION
publishedGroupId = GROUP
libraryName = 'yoga'
artifact = 'yoga'
developerId = POM_DEVELOPER_ID
developerName = POM_DEVELOPER_NAME
projectLicenses = {
license {
name = POM_LICENSE_NAME
url = POM_LICENSE_URL
distribution = POM_LICENSE_DIST
}
}
}
// Set up the Android Maven publication (POM etc.)
apply from: rootProject.file('gradle/android-maven-install.gradle')
// Upload to Bintray
apply from: rootProject.file('gradle/bintray.gradle')

View File

@@ -1,15 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// Common Android tasks for all releases that generate Javadocs, sources, etc.
apply from: rootProject.file('gradle/android-tasks.gradle')
// Upload to Bintray
apply from: rootProject.file('gradle/release-bintray.gradle')
// Upload directly to standard Maven Central (for SNAPSHOTs)
apply from: rootProject.file('gradle/gradle-mvn-push.gradle')

View File

@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip

View File

@@ -3,11 +3,11 @@
# This source code is licensed under the MIT license found in the # This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree. # LICENSE file in the root directory of this source tree.
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID", "CXX_LIBRARY_WHITELIST", "JNI_TARGET", "JSR_305_TARGET", "JUNIT_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "YOGA_ROOTS", "yoga_cxx_lib", "yoga_cxx_library", "yoga_dep", "yoga_java_binary", "yoga_java_library", "yoga_java_test", "yoga_prebuilt_cxx_library") load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID", "CXX_LIBRARY_WHITELIST", "JNI_TARGET", "JSR_305_TARGET", "JUNIT_TARGET", "PROGUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "YOGA_ROOTS", "yoga_cxx_lib", "yoga_cxx_library", "yoga_dep", "yoga_java_binary", "yoga_java_library", "yoga_java_test", "yoga_prebuilt_cxx_library")
CXX_LIBRARY_WHITELIST_FOR_TESTS = CXX_LIBRARY_WHITELIST + [ CXX_LIBRARY_WHITELIST_FOR_TESTS = CXX_LIBRARY_WHITELIST + [
yoga_cxx_lib("testutil:jni"), yoga_cxx_lib("testutil:jni"),
yoga_cxx_lib("testutil:testutil"), yoga_cxx_lib("testutil:testutil-jni"),
] ]
YOGA_JAVA_IMPLEMENTATION_FILES = [ YOGA_JAVA_IMPLEMENTATION_FILES = [
@@ -54,7 +54,7 @@ yoga_cxx_library(
visibility = ["PUBLIC"], visibility = ["PUBLIC"],
deps = [ deps = [
JNI_TARGET, JNI_TARGET,
yoga_dep(":yoga"), yoga_dep(":yoga-static"),
":ndklog", ":ndklog",
], ],
) )
@@ -71,7 +71,7 @@ yoga_java_library(
visibility = ["PUBLIC"], visibility = ["PUBLIC"],
deps = [ deps = [
JSR_305_TARGET, JSR_305_TARGET,
PROGRUARD_ANNOTATIONS_TARGET, PROGUARD_ANNOTATIONS_TARGET,
], ],
) )
@@ -85,7 +85,7 @@ yoga_java_library(
":java-interface", ":java-interface",
":jni", ":jni",
JSR_305_TARGET, JSR_305_TARGET,
PROGRUARD_ANNOTATIONS_TARGET, PROGUARD_ANNOTATIONS_TARGET,
SOLOADER_TARGET, SOLOADER_TARGET,
], ],
) )
@@ -108,6 +108,7 @@ yoga_java_library(
yoga_java_test( yoga_java_test(
name = "tests", name = "tests",
srcs = glob(["tests/**/*.java"]), srcs = glob(["tests/**/*.java"]),
contacts = ["oncall+yoga@xmail.facebook.com"],
cxx_library_whitelist = CXX_LIBRARY_WHITELIST_FOR_TESTS, cxx_library_whitelist = CXX_LIBRARY_WHITELIST_FOR_TESTS,
use_cxx_libraries = True, use_cxx_libraries = True,
visibility = ["PUBLIC"], visibility = ["PUBLIC"],

View File

@@ -5,17 +5,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
apply plugin: 'com.jfrog.bintray'
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'maven-publish'
group = GROUP
version = VERSION_NAME
android { android {
compileSdkVersion rootProject.compileSdkVersion compileSdkVersion rootProject.compileSdkVersion
buildToolsVersion rootProject.buildToolsVersion buildToolsVersion rootProject.buildToolsVersion
ndkVersion rootProject.ndkVersion
defaultConfig { defaultConfig {
minSdkVersion rootProject.minSdkVersion minSdkVersion rootProject.minSdkVersion
@@ -35,7 +30,6 @@ android {
externalNativeBuild { externalNativeBuild {
cmake { cmake {
path 'CMakeLists.txt' path 'CMakeLists.txt'
version '3.6.0-rc2'
} }
} }
@@ -58,32 +52,11 @@ android {
} }
dependencies { dependencies {
implementation 'com.google.code.findbugs:jsr305:3.0.1' implementation 'com.google.code.findbugs:jsr305:3.0.2'
implementation project(':yoga:proguard-annotations') implementation project(':yoga:proguard-annotations')
implementation 'com.facebook.soloader:soloader:0.5.1' implementation 'com.facebook.soloader:soloader:0.10.1'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation project(':testutil') testImplementation project(':testutil')
} }
task sourcesJar(type: Jar) { apply plugin: 'com.vanniktech.maven.publish'
classifier = 'source'
from android.sourceSets.main.java.srcDirs
}
task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
ext {
bintrayName = 'com.facebook.yoga:yoga'
}
apply from: rootProject.file('gradle/release.gradle')

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaAlign { public enum YogaAlign {
AUTO(0), AUTO(0),
FLEX_START(1), FLEX_START(1),

View File

@@ -7,14 +7,10 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public interface YogaBaselineFunction { public interface YogaBaselineFunction {
/** /**
* Return the baseline of the node in points. When no baseline function is set the baseline * Return the baseline of the node in points. When no baseline function is set the baseline
* default to the computed height of the node. * default to the computed height of the node.
*/ */
@DoNotStrip
float baseline(YogaNode node, float width, float height); float baseline(YogaNode node, float width, float height);
} }

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaDimension { public enum YogaDimension {
WIDTH(0), WIDTH(0),
HEIGHT(1); HEIGHT(1);

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaDirection { public enum YogaDirection {
INHERIT(0), INHERIT(0),
LTR(1), LTR(1),

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaDisplay { public enum YogaDisplay {
FLEX(0), FLEX(0),
NONE(1); NONE(1);

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaEdge { public enum YogaEdge {
LEFT(0), LEFT(0),
TOP(1), TOP(1),

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaExperimentalFeature { public enum YogaExperimentalFeature {
WEB_FLEX_BASIS(0); WEB_FLEX_BASIS(0);

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaFlexDirection { public enum YogaFlexDirection {
COLUMN(0), COLUMN(0),
COLUMN_REVERSE(1), COLUMN_REVERSE(1),

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaJustify { public enum YogaJustify {
FLEX_START(0), FLEX_START(0),
CENTER(1), CENTER(1),

View File

@@ -28,6 +28,7 @@ public enum YogaLogLevel {
return mIntValue; return mIntValue;
} }
@DoNotStrip
public static YogaLogLevel fromInt(int value) { public static YogaLogLevel fromInt(int value) {
switch (value) { switch (value) {
case 0: return ERROR; case 0: return ERROR;

View File

@@ -7,14 +7,10 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public interface YogaMeasureFunction { public interface YogaMeasureFunction {
/** /**
* Return a value created by YogaMeasureOutput.make(width, height); * Return a value created by YogaMeasureOutput.make(width, height);
*/ */
@DoNotStrip
long measure( long measure(
YogaNode node, YogaNode node,
float width, float width,

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaMeasureMode { public enum YogaMeasureMode {
UNDEFINED(0), UNDEFINED(0),
EXACTLY(1), EXACTLY(1),

View File

@@ -34,6 +34,7 @@ public class YogaNative {
static native void jni_YGNodeFreeJNI(long nativePointer); static native void jni_YGNodeFreeJNI(long nativePointer);
static native void jni_YGNodeResetJNI(long nativePointer); static native void jni_YGNodeResetJNI(long nativePointer);
static native void jni_YGNodeInsertChildJNI(long nativePointer, long childPointer, int index); static native void jni_YGNodeInsertChildJNI(long nativePointer, long childPointer, int index);
static native void jni_YGNodeSwapChildJNI(long nativePointer, long childPointer, int index);
static native void jni_YGNodeSetIsReferenceBaselineJNI(long nativePointer, boolean isReferenceBaseline); static native void jni_YGNodeSetIsReferenceBaselineJNI(long nativePointer, boolean isReferenceBaseline);
static native boolean jni_YGNodeIsReferenceBaselineJNI(long nativePointer); static native boolean jni_YGNodeIsReferenceBaselineJNI(long nativePointer);
static native void jni_YGNodeClearChildrenJNI(long nativePointer); static native void jni_YGNodeClearChildrenJNI(long nativePointer);

View File

@@ -9,7 +9,15 @@ package com.facebook.yoga;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public abstract class YogaNode { public abstract class YogaNode implements YogaProps {
/** The interface the {@link #getData()} object can optionally implement. */
public interface Inputs {
/** Requests the data object to disable mutations of its inputs. */
void freeze(final YogaNode node, final @Nullable YogaNode parent);
}
public abstract void reset(); public abstract void reset();
public abstract int getChildCount(); public abstract int getChildCount();
@@ -25,12 +33,10 @@ public abstract class YogaNode {
public abstract YogaNode removeChildAt(int i); public abstract YogaNode removeChildAt(int i);
/** /**
* @returns the {@link YogaNode} that owns this {@link YogaNode}. * @returns the {@link YogaNode} that owns this {@link YogaNode}. The owner is used to identify
* The owner is used to identify the YogaTree that a {@link YogaNode} belongs * the YogaTree that a {@link YogaNode} belongs to. This method will return the parent of the
* to. * {@link YogaNode} when the {@link YogaNode} only belongs to one YogaTree or null when the
* This method will return the parent of the {@link YogaNode} when the * {@link YogaNode} is shared between two or more YogaTrees.
* {@link YogaNode} only belongs to one YogaTree or null when the
* {@link YogaNode} is shared between two or more YogaTrees.
*/ */
@Nullable @Nullable
public abstract YogaNode getOwner(); public abstract YogaNode getOwner();
@@ -214,4 +220,6 @@ public abstract class YogaNode {
public abstract void print(); public abstract void print();
public abstract YogaNode cloneWithoutChildren(); public abstract YogaNode cloneWithoutChildren();
public abstract YogaNode cloneWithChildren();
} }

View File

@@ -15,7 +15,7 @@ import javax.annotation.Nullable;
@DoNotStrip @DoNotStrip
public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
/* Those flags needs be in sync with YGJNI.cpp */ /* Those flags needs be in sync with YGJNI.h */
private static final byte MARGIN = 1; private static final byte MARGIN = 1;
private static final byte PADDING = 2; private static final byte PADDING = 2;
private static final byte BORDER = 4; private static final byte BORDER = 4;
@@ -39,11 +39,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
protected long mNativePointer; protected long mNativePointer;
@Nullable private Object mData; @Nullable private Object mData;
@DoNotStrip @DoNotStrip private @Nullable float[] arr = null;
private @Nullable float[] arr = null;
@DoNotStrip @DoNotStrip private int mLayoutDirection = 0;
private int mLayoutDirection = 0;
private boolean mHasNewLayout = true; private boolean mHasNewLayout = true;
@@ -59,7 +57,7 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
} }
YogaNodeJNIBase(YogaConfig config) { YogaNodeJNIBase(YogaConfig config) {
this(YogaNative.jni_YGNodeNewWithConfigJNI(((YogaConfigJNIBase)config).mNativePointer)); this(YogaNative.jni_YGNodeNewWithConfigJNI(((YogaConfigJNIBase) config).mNativePointer));
} }
public void reset() { public void reset() {
@@ -85,6 +83,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
} }
public void addChildAt(YogaNode c, int i) { public void addChildAt(YogaNode c, int i) {
if (!(c instanceof YogaNodeJNIBase)) {
return;
}
YogaNodeJNIBase child = (YogaNodeJNIBase) c; YogaNodeJNIBase child = (YogaNodeJNIBase) c;
if (child.mOwner != null) { if (child.mOwner != null) {
throw new IllegalStateException("Child already has a parent, it must be removed first."); throw new IllegalStateException("Child already has a parent, it must be removed first.");
@@ -106,6 +107,38 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
return YogaNative.jni_YGNodeIsReferenceBaselineJNI(mNativePointer); return YogaNative.jni_YGNodeIsReferenceBaselineJNI(mNativePointer);
} }
public void swapChildAt(YogaNode newChild, int position) {
if (!(newChild instanceof YogaNodeJNIBase)) {
return;
}
YogaNodeJNIBase child = (YogaNodeJNIBase) newChild;
mChildren.remove(position);
mChildren.add(position, child);
child.mOwner = this;
YogaNative.jni_YGNodeSwapChildJNI(mNativePointer, child.mNativePointer, position);
}
@Override
public YogaNodeJNIBase cloneWithChildren() {
try {
YogaNodeJNIBase clonedYogaNode = (YogaNodeJNIBase) super.clone();
if (clonedYogaNode.mChildren != null) {
clonedYogaNode.mChildren = new ArrayList<>(clonedYogaNode.mChildren);
}
long clonedNativePointer = YogaNative.jni_YGNodeCloneJNI(mNativePointer);
clonedYogaNode.mOwner = null;
clonedYogaNode.mNativePointer = clonedNativePointer;
for (int i = 0; i < clonedYogaNode.getChildCount(); i++) {
clonedYogaNode.swapChildAt(clonedYogaNode.getChildAt(i).cloneWithChildren(), i);
}
return clonedYogaNode;
} catch (CloneNotSupportedException ex) {
// This class implements Cloneable, this should not happen
throw new RuntimeException(ex);
}
}
@Override @Override
public YogaNodeJNIBase cloneWithoutChildren() { public YogaNodeJNIBase cloneWithoutChildren() {
try { try {
@@ -138,12 +171,11 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
} }
/** /**
* @returns the {@link YogaNode} that owns this {@link YogaNode}. * The owner is used to identify the YogaTree that a {@link YogaNode} belongs to. This method will
* The owner is used to identify the YogaTree that a {@link YogaNode} belongs * return the parent of the {@link YogaNode} when the {@link YogaNode} only belongs to one
* to. * YogaTree or null when the {@link YogaNode} is shared between two or more YogaTrees.
* This method will return the parent of the {@link YogaNode} when the *
* {@link YogaNode} only belongs to one YogaTree or null when the * @return the {@link YogaNode} that owns this {@link YogaNode}.
* {@link YogaNode} is shared between two or more YogaTrees.
*/ */
@Nullable @Nullable
public YogaNodeJNIBase getOwner() { public YogaNodeJNIBase getOwner() {
@@ -165,12 +197,18 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
long[] nativePointers = null; long[] nativePointers = null;
YogaNodeJNIBase[] nodes = null; YogaNodeJNIBase[] nodes = null;
freeze(null);
ArrayList<YogaNodeJNIBase> n = new ArrayList<>(); ArrayList<YogaNodeJNIBase> n = new ArrayList<>();
n.add(this); n.add(this);
for (int i = 0; i < n.size(); ++i) { for (int i = 0; i < n.size(); ++i) {
List<YogaNodeJNIBase> children = n.get(i).mChildren; final YogaNodeJNIBase parent = n.get(i);
List<YogaNodeJNIBase> children = parent.mChildren;
if (children != null) { if (children != null) {
n.addAll(children); for (YogaNodeJNIBase child : children) {
child.freeze(parent);
n.add(child);
}
} }
} }
@@ -183,6 +221,13 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
YogaNative.jni_YGNodeCalculateLayoutJNI(mNativePointer, width, height, nativePointers, nodes); YogaNative.jni_YGNodeCalculateLayoutJNI(mNativePointer, width, height, nativePointers, nodes);
} }
private void freeze(YogaNode parent) {
Object data = getData();
if (data instanceof Inputs) {
((Inputs) data).freeze(this, parent);
}
}
public void dirty() { public void dirty() {
YogaNative.jni_YGNodeMarkDirtyJNI(mNativePointer); YogaNative.jni_YGNodeMarkDirtyJNI(mNativePointer);
} }
@@ -197,6 +242,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
@Override @Override
public void copyStyle(YogaNode srcNode) { public void copyStyle(YogaNode srcNode) {
if (!(srcNode instanceof YogaNodeJNIBase)) {
return;
}
YogaNative.jni_YGNodeCopyStyleJNI(mNativePointer, ((YogaNodeJNIBase) srcNode).mNativePointer); YogaNative.jni_YGNodeCopyStyleJNI(mNativePointer, ((YogaNodeJNIBase) srcNode).mNativePointer);
} }
@@ -509,8 +557,8 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
} }
/** /**
* Use the set logger (defaults to adb log) to print out the styles, children, and computed * Use the set logger (defaults to adb log) to print out the styles, children, and computed layout
* layout of the tree rooted at this node. * of the tree rooted at this node.
*/ */
public void print() { public void print() {
YogaNative.jni_YGNodePrintJNI(mNativePointer); YogaNative.jni_YGNodePrintJNI(mNativePointer);
@@ -521,7 +569,7 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
* This is different than calling removeChildAt and addChildAt because this method ONLY replaces * This is different than calling removeChildAt and addChildAt because this method ONLY replaces
* the child in the mChildren datastructure. @DoNotStrip: called from JNI * the child in the mChildren datastructure. @DoNotStrip: called from JNI
* *
* @return the nativePointer of the newNode {@linl YogaNode} * @return the nativePointer of the newNode {@link YogaNode}
*/ */
@DoNotStrip @DoNotStrip
private final long replaceChild(YogaNodeJNIBase newNode, int childIndex) { private final long replaceChild(YogaNodeJNIBase newNode, int childIndex) {
@@ -559,7 +607,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
} }
public boolean getDoesLegacyStretchFlagAffectsLayout() { public boolean getDoesLegacyStretchFlagAffectsLayout() {
return arr != null && (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & DOES_LEGACY_STRETCH_BEHAVIOUR) == DOES_LEGACY_STRETCH_BEHAVIOUR); return arr != null
&& (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & DOES_LEGACY_STRETCH_BEHAVIOUR)
== DOES_LEGACY_STRETCH_BEHAVIOUR);
} }
@Override @Override
@@ -575,9 +625,13 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
case BOTTOM: case BOTTOM:
return arr[LAYOUT_MARGIN_START_INDEX + 3]; return arr[LAYOUT_MARGIN_START_INDEX + 3];
case START: case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX + 2] : arr[LAYOUT_MARGIN_START_INDEX]; return getLayoutDirection() == YogaDirection.RTL
? arr[LAYOUT_MARGIN_START_INDEX + 2]
: arr[LAYOUT_MARGIN_START_INDEX];
case END: case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX] : arr[LAYOUT_MARGIN_START_INDEX + 2]; return getLayoutDirection() == YogaDirection.RTL
? arr[LAYOUT_MARGIN_START_INDEX]
: arr[LAYOUT_MARGIN_START_INDEX + 2];
default: default:
throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands"); throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands");
} }
@@ -589,7 +643,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
@Override @Override
public float getLayoutPadding(YogaEdge edge) { public float getLayoutPadding(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) { if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) {
int paddingStartIndex = LAYOUT_PADDING_START_INDEX - ((((int)arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4); int paddingStartIndex =
LAYOUT_PADDING_START_INDEX
- ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4);
switch (edge) { switch (edge) {
case LEFT: case LEFT:
return arr[paddingStartIndex]; return arr[paddingStartIndex];
@@ -600,9 +656,13 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
case BOTTOM: case BOTTOM:
return arr[paddingStartIndex + 3]; return arr[paddingStartIndex + 3];
case START: case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex + 2] : arr[paddingStartIndex]; return getLayoutDirection() == YogaDirection.RTL
? arr[paddingStartIndex + 2]
: arr[paddingStartIndex];
case END: case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex] : arr[paddingStartIndex + 2]; return getLayoutDirection() == YogaDirection.RTL
? arr[paddingStartIndex]
: arr[paddingStartIndex + 2];
default: default:
throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands"); throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands");
} }
@@ -614,7 +674,10 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
@Override @Override
public float getLayoutBorder(YogaEdge edge) { public float getLayoutBorder(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & BORDER) == BORDER) { if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & BORDER) == BORDER) {
int borderStartIndex = LAYOUT_BORDER_START_INDEX - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4) - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) ? 0 : 4); int borderStartIndex =
LAYOUT_BORDER_START_INDEX
- ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4)
- ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) ? 0 : 4);
switch (edge) { switch (edge) {
case LEFT: case LEFT:
return arr[borderStartIndex]; return arr[borderStartIndex];
@@ -625,9 +688,13 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
case BOTTOM: case BOTTOM:
return arr[borderStartIndex + 3]; return arr[borderStartIndex + 3];
case START: case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex + 2] : arr[borderStartIndex]; return getLayoutDirection() == YogaDirection.RTL
? arr[borderStartIndex + 2]
: arr[borderStartIndex];
case END: case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex] : arr[borderStartIndex + 2]; return getLayoutDirection() == YogaDirection.RTL
? arr[borderStartIndex]
: arr[borderStartIndex + 2];
default: default:
throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands"); throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands");
} }
@@ -638,7 +705,8 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
@Override @Override
public YogaDirection getLayoutDirection() { public YogaDirection getLayoutDirection() {
return YogaDirection.fromInt(arr != null ? (int) arr[LAYOUT_DIRECTION_INDEX] : mLayoutDirection); return YogaDirection.fromInt(
arr != null ? (int) arr[LAYOUT_DIRECTION_INDEX] : mLayoutDirection);
} }
@Override @Override

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaNodeType { public enum YogaNodeType {
DEFAULT(0), DEFAULT(0),
TEXT(1); TEXT(1);

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaOverflow { public enum YogaOverflow {
VISIBLE(0), VISIBLE(0),
HIDDEN(1), HIDDEN(1),

View File

@@ -7,12 +7,10 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaPositionType { public enum YogaPositionType {
RELATIVE(0), STATIC(0),
ABSOLUTE(1); RELATIVE(1),
ABSOLUTE(2);
private final int mIntValue; private final int mIntValue;
@@ -26,8 +24,9 @@ public enum YogaPositionType {
public static YogaPositionType fromInt(int value) { public static YogaPositionType fromInt(int value) {
switch (value) { switch (value) {
case 0: return RELATIVE; case 0: return STATIC;
case 1: return ABSOLUTE; case 1: return RELATIVE;
case 2: return ABSOLUTE;
default: throw new IllegalArgumentException("Unknown enum value: " + value); default: throw new IllegalArgumentException("Unknown enum value: " + value);
} }
} }

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaPrintOptions { public enum YogaPrintOptions {
LAYOUT(1), LAYOUT(1),
STYLE(2), STYLE(2),

View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.yoga;
public interface YogaProps {
/* Width properties */
void setWidth(float width);
void setWidthPercent(float percent);
void setMinWidth(float minWidth);
void setMinWidthPercent(float percent);
void setMaxWidth(float maxWidth);
void setMaxWidthPercent(float percent);
void setWidthAuto();
/* Height properties */
void setHeight(float height);
void setHeightPercent(float percent);
void setMinHeight(float minHeight);
void setMinHeightPercent(float percent);
void setMaxHeight(float maxHeight);
void setMaxHeightPercent(float percent);
void setHeightAuto();
/* Margin properties */
void setMargin(YogaEdge edge, float margin);
void setMarginPercent(YogaEdge edge, float percent);
void setMarginAuto(YogaEdge edge);
/* Padding properties */
void setPadding(YogaEdge edge, float padding);
void setPaddingPercent(YogaEdge edge, float percent);
/* Position properties */
void setPositionType(YogaPositionType positionType);
void setPosition(YogaEdge edge, float position);
void setPositionPercent(YogaEdge edge, float percent);
/* Alignment properties */
void setAlignContent(YogaAlign alignContent);
void setAlignItems(YogaAlign alignItems);
void setAlignSelf(YogaAlign alignSelf);
/* Flex properties */
void setFlex(float flex);
void setFlexBasisAuto();
void setFlexBasisPercent(float percent);
void setFlexBasis(float flexBasis);
void setFlexDirection(YogaFlexDirection direction);
void setFlexGrow(float flexGrow);
void setFlexShrink(float flexShrink);
/* Other properties */
void setJustifyContent(YogaJustify justifyContent);
void setDirection(YogaDirection direction);
void setBorder(YogaEdge edge, float value);
void setWrap(YogaWrap wrap);
void setAspectRatio(float aspectRatio);
void setIsReferenceBaseline(boolean isReferenceBaseline);
void setMeasureFunction(YogaMeasureFunction measureFunction);
void setBaselineFunction(YogaBaselineFunction yogaBaselineFunction);
/* Getters */
YogaValue getWidth();
YogaValue getMinWidth();
YogaValue getMaxWidth();
YogaValue getHeight();
YogaValue getMinHeight();
YogaValue getMaxHeight();
YogaDirection getStyleDirection();
YogaFlexDirection getFlexDirection();
YogaJustify getJustifyContent();
YogaAlign getAlignItems();
YogaAlign getAlignSelf();
YogaAlign getAlignContent();
YogaPositionType getPositionType();
float getFlexGrow();
float getFlexShrink();
YogaValue getFlexBasis();
float getAspectRatio();
YogaValue getMargin(YogaEdge edge);
YogaValue getPadding(YogaEdge edge);
YogaValue getPosition(YogaEdge edge);
float getBorder(YogaEdge edge);
}

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public class YogaStyleInputs { public class YogaStyleInputs {
public static final short LAYOUT_DIRECTION = 0; public static final short LAYOUT_DIRECTION = 0;
public static final short FLEX_DIRECTION = 1; public static final short FLEX_DIRECTION = 1;

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaUnit { public enum YogaUnit {
UNDEFINED(0), UNDEFINED(0),
POINT(1), POINT(1),

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaWrap { public enum YogaWrap {
NO_WRAP(0), NO_WRAP(0),
WRAP(1), WRAP(1),

View File

@@ -84,9 +84,7 @@ public:
return *this; return *this;
} }
~ScopedGlobalRef() { ~ScopedGlobalRef() { reset(); }
reset();
}
/** /**
* Deletes the currently held reference and reassigns a new one to the * Deletes the currently held reference and reassigns a new one to the
@@ -120,9 +118,7 @@ public:
/** /**
* Returns true if the underlying JNI reference is not NULL. * Returns true if the underlying JNI reference is not NULL.
*/ */
operator bool() const { operator bool() const { return mGlobalRef != NULL; }
return mGlobalRef != NULL;
}
ScopedGlobalRef(const ScopedGlobalRef& ref) = delete; ScopedGlobalRef(const ScopedGlobalRef& ref) = delete;
ScopedGlobalRef& operator=(const ScopedGlobalRef& other) = delete; ScopedGlobalRef& operator=(const ScopedGlobalRef& other) = delete;

View File

@@ -83,9 +83,7 @@ public:
return *this; return *this;
} }
~ScopedLocalRef() { ~ScopedLocalRef() { reset(); }
reset();
}
/** /**
* Deletes the currently held reference and reassigns a new one to the * Deletes the currently held reference and reassigns a new one to the
@@ -119,9 +117,7 @@ public:
/** /**
* Returns true if the underlying JNI reference is not NULL. * Returns true if the underlying JNI reference is not NULL.
*/ */
operator bool() const { operator bool() const { return mLocalRef != NULL; }
return mLocalRef != NULL;
}
ScopedLocalRef(const ScopedLocalRef& ref) = delete; ScopedLocalRef(const ScopedLocalRef& ref) = delete;
ScopedLocalRef& operator=(const ScopedLocalRef& other) = delete; ScopedLocalRef& operator=(const ScopedLocalRef& other) = delete;

View File

@@ -15,6 +15,7 @@
#include <yoga/log.h> #include <yoga/log.h>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include "YogaJniException.h"
using namespace facebook::yoga::vanillajni; using namespace facebook::yoga::vanillajni;
using facebook::yoga::detail::Log; using facebook::yoga::detail::Log;
@@ -195,7 +196,7 @@ static void jni_YGConfigSetLoggerJNI(
delete context; delete context;
YGConfigSetContext(config, nullptr); YGConfigSetContext(config, nullptr);
} }
config->setLogger(nullptr); YGConfigSetLogger(config, nullptr);
} }
} }
@@ -224,6 +225,16 @@ static void jni_YGNodeInsertChildJNI(
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index);
} }
static void jni_YGNodeSwapChildJNI(
JNIEnv* env,
jobject obj,
jlong nativePointer,
jlong childPointer,
jint index) {
YGNodeSwapChild(
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index);
}
static void jni_YGNodeSetIsReferenceBaselineJNI( static void jni_YGNodeSetIsReferenceBaselineJNI(
JNIEnv* env, JNIEnv* env,
jobject obj, jobject obj,
@@ -372,8 +383,18 @@ static void jni_YGNodeCalculateLayoutJNI(
YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer)), YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer)),
layoutContext); layoutContext);
YGTransferLayoutOutputsRecursive(env, obj, root, layoutContext); YGTransferLayoutOutputsRecursive(env, obj, root, layoutContext);
} catch (jthrowable throwable) { } catch (const YogaJniException& jniException) {
env->Throw(throwable); ScopedLocalRef<jthrowable> throwable = jniException.getThrowable();
if (throwable.get()) {
env->Throw(throwable.get());
}
} catch (const std::logic_error& ex) {
env->ExceptionClear();
jclass cl = env->FindClass("Ljava/lang/IllegalStateException;");
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
env, cl, "<init>", "(Ljava/lang/String;)V");
auto throwable = env->NewObject(cl, methodId, env->NewStringUTF(ex.what()));
env->Throw(static_cast<jthrowable>(throwable));
} }
} }
@@ -705,8 +726,7 @@ static void jni_YGNodePrintJNI(JNIEnv* env, jobject obj, jlong nativePointer) {
const YGNodeRef node = _jlong2YGNodeRef(nativePointer); const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
YGNodePrint( YGNodePrint(
node, node,
(YGPrintOptions)( (YGPrintOptions) (YGPrintOptionsStyle | YGPrintOptionsLayout | YGPrintOptionsChildren));
YGPrintOptionsStyle | YGPrintOptionsLayout | YGPrintOptionsChildren));
#endif #endif
} }
@@ -750,6 +770,7 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeFreeJNI", "(J)V", (void*) jni_YGNodeFreeJNI}, {"jni_YGNodeFreeJNI", "(J)V", (void*) jni_YGNodeFreeJNI},
{"jni_YGNodeResetJNI", "(J)V", (void*) jni_YGNodeResetJNI}, {"jni_YGNodeResetJNI", "(J)V", (void*) jni_YGNodeResetJNI},
{"jni_YGNodeInsertChildJNI", "(JJI)V", (void*) jni_YGNodeInsertChildJNI}, {"jni_YGNodeInsertChildJNI", "(JJI)V", (void*) jni_YGNodeInsertChildJNI},
{"jni_YGNodeSwapChildJNI", "(JJI)V", (void*) jni_YGNodeSwapChildJNI},
{"jni_YGNodeSetIsReferenceBaselineJNI", {"jni_YGNodeSetIsReferenceBaselineJNI",
"(JZ)V", "(JZ)V",
(void*) jni_YGNodeSetIsReferenceBaselineJNI}, (void*) jni_YGNodeSetIsReferenceBaselineJNI},

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <stdexcept>
#include <string>
#include "YogaJniException.h"
#include "common.h"
namespace facebook {
namespace yoga {
namespace vanillajni {
YogaJniException::YogaJniException() {
jclass cl = getCurrentEnv()->FindClass("Ljava/lang/RuntimeException;");
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
getCurrentEnv(), cl, "<init>", "()V");
auto throwable = getCurrentEnv()->NewObject(cl, methodId);
throwable_ =
newGlobalRef(getCurrentEnv(), static_cast<jthrowable>(throwable));
}
YogaJniException::YogaJniException(jthrowable throwable) {
throwable_ = newGlobalRef(getCurrentEnv(), throwable);
}
YogaJniException::YogaJniException(YogaJniException&& rhs)
: throwable_(std::move(rhs.throwable_)) {}
YogaJniException::YogaJniException(const YogaJniException& rhs) {
throwable_ = newGlobalRef(getCurrentEnv(), rhs.throwable_.get());
}
YogaJniException::~YogaJniException() {
try {
throwable_.reset();
} catch (...) {
std::terminate();
}
}
ScopedLocalRef<jthrowable> YogaJniException::getThrowable() const noexcept {
return make_local_ref(
getCurrentEnv(),
static_cast<jthrowable>(getCurrentEnv()->NewLocalRef(throwable_.get())));
}
} // namespace vanillajni
} // namespace yoga
} // namespace facebook

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <stdexcept>
#include <string>
#include "common.h"
namespace facebook {
namespace yoga {
namespace vanillajni {
/**
* This class wraps a Java exception (jthrowable) into a C++ exception; A global
* reference to Java exception (jthrowable) is made so that the exception object
* does not gets cleared before jni call completion
*/
class YogaJniException : public std::exception {
public:
YogaJniException();
~YogaJniException() override;
explicit YogaJniException(jthrowable throwable);
YogaJniException(YogaJniException&& rhs);
YogaJniException(const YogaJniException& other);
ScopedLocalRef<jthrowable> getThrowable() const noexcept;
private:
ScopedGlobalRef<jthrowable> throwable_;
};
} // namespace vanillajni
} // namespace yoga
} // namespace facebook

View File

@@ -18,11 +18,11 @@ void registerNatives(
size_t numMethods) { size_t numMethods) {
jclass clazz = env->FindClass(className); jclass clazz = env->FindClass(className);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !clazz);
env->RegisterNatives(clazz, methods, numMethods); auto result = env->RegisterNatives(clazz, methods, numMethods);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, result != JNI_OK);
} }
jmethodID getStaticMethodId( jmethodID getStaticMethodId(
@@ -32,7 +32,7 @@ jmethodID getStaticMethodId(
const char* methodDescriptor) { const char* methodDescriptor) {
jmethodID methodId = jmethodID methodId =
env->GetStaticMethodID(clazz, methodName, methodDescriptor); env->GetStaticMethodID(clazz, methodName, methodDescriptor);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !methodId);
return methodId; return methodId;
} }
@@ -42,7 +42,7 @@ jmethodID getMethodId(
const char* methodName, const char* methodName,
const char* methodDescriptor) { const char* methodDescriptor) {
jmethodID methodId = env->GetMethodID(clazz, methodName, methodDescriptor); jmethodID methodId = env->GetMethodID(clazz, methodName, methodDescriptor);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !methodId);
return methodId; return methodId;
} }
@@ -52,7 +52,7 @@ jfieldID getFieldId(
const char* fieldName, const char* fieldName,
const char* fieldSignature) { const char* fieldSignature) {
jfieldID fieldId = env->GetFieldID(clazz, fieldName, fieldSignature); jfieldID fieldId = env->GetFieldID(clazz, fieldName, fieldSignature);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !fieldId);
return fieldId; return fieldId;
} }
@@ -77,13 +77,16 @@ DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(void, Void) {
assertNoPendingJniException(env); assertNoPendingJniException(env);
} }
ScopedLocalRef<jobject> ScopedLocalRef<jobject> callStaticObjectMethod(
callStaticObjectMethod(JNIEnv* env, jclass clazz, jmethodID methodId, ...) { JNIEnv* env,
jclass clazz,
jmethodID methodId,
...) {
va_list args; va_list args;
va_start(args, methodId); va_start(args, methodId);
jobject result = env->CallStaticObjectMethodV(clazz, methodId, args); jobject result = env->CallStaticObjectMethodV(clazz, methodId, args);
va_end(args); va_end(args);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !result);
return make_local_ref(env, result); return make_local_ref(env, result);
} }
@@ -96,6 +99,16 @@ ScopedGlobalRef<jobject> newGlobalRef(JNIEnv* env, jobject obj) {
return make_global_ref(result); return make_global_ref(result);
} }
ScopedGlobalRef<jthrowable> newGlobalRef(JNIEnv* env, jthrowable obj) {
jthrowable result = static_cast<jthrowable>(env->NewGlobalRef(obj));
if (!result) {
logErrorMessageAndDie("Could not obtain global reference from object");
}
return make_global_ref(result);
}
} // namespace vanillajni } // namespace vanillajni
} // namespace yoga } // namespace yoga
} // namespace facebook } // namespace facebook

View File

@@ -61,14 +61,19 @@ DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(void, Void);
DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(jlong, Long); DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(jlong, Long);
DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(jfloat, Float); DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(jfloat, Float);
ScopedLocalRef<jobject> ScopedLocalRef<jobject> callStaticObjectMethod(
callStaticObjectMethod(JNIEnv* env, jclass clazz, jmethodID methodId, ...); JNIEnv* env,
jclass clazz,
jmethodID methodId,
...);
/** /**
* Given a local or a global reference, this method creates a new global * Given a local or a global reference, this method creates a new global
* reference out of it. If any error happens, aborts the process. * reference out of it. If any error happens, aborts the process.
*/ */
ScopedGlobalRef<jobject> newGlobalRef(JNIEnv* env, jobject obj); ScopedGlobalRef<jobject> newGlobalRef(JNIEnv* env, jobject obj);
ScopedGlobalRef<jthrowable> newGlobalRef(JNIEnv* env, jthrowable obj);
} // namespace vanillajni } // namespace vanillajni
} // namespace yoga } // namespace yoga
} // namespace facebook } // namespace facebook

View File

@@ -7,6 +7,7 @@
#include "corefunctions.h" #include "corefunctions.h"
#include "macros.h" #include "macros.h"
#include "YogaJniException.h"
namespace facebook { namespace facebook {
namespace yoga { namespace yoga {
@@ -72,7 +73,20 @@ void assertNoPendingJniException(JNIEnv* env) {
logErrorMessageAndDie("Unable to get pending JNI exception."); logErrorMessageAndDie("Unable to get pending JNI exception.");
} }
env->ExceptionClear(); env->ExceptionClear();
throw throwable; throw YogaJniException(throwable);
}
void assertNoPendingJniExceptionIf(JNIEnv* env, bool condition) {
if (!condition) {
return;
}
if (env->ExceptionCheck() == JNI_TRUE) {
assertNoPendingJniException(env);
return;
}
throw YogaJniException();
} }
} // namespace vanillajni } // namespace vanillajni

View File

@@ -47,6 +47,8 @@ void logErrorMessageAndDie(const char* message);
*/ */
void assertNoPendingJniException(JNIEnv* env); void assertNoPendingJniException(JNIEnv* env);
void assertNoPendingJniExceptionIf(JNIEnv* env, bool condition);
} // namespace vanillajni } // namespace vanillajni
} // namespace yoga } // namespace yoga
} // namespace facebook } // namespace facebook

View File

@@ -10,4 +10,4 @@ apply plugin: 'java'
sourceCompatibility = '1.7' sourceCompatibility = '1.7'
targetCompatibility = '1.7' targetCompatibility = '1.7'
apply from: rootProject.file('gradle/release.gradle') apply plugin: 'com.vanniktech.maven.publish'

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.proguard.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.CLASS;
/**
* Add this annotation to a class to instruct Proguard to not strip it or any of its fields or
* methods out.
*
* <p>This is useful for methods called via reflection that could appear as unused to Proguard.
*/
@Target({ElementType.TYPE})
@Retention(CLASS)
public @interface DoNotStripAny {}

View File

@@ -1,9 +1,10 @@
/** /*
* Copyright (c) Facebook, Inc. and its affiliates. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the LICENSE * This source code is licensed under the MIT license found in the
* file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// @Generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html // @Generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html
package com.facebook.yoga; package com.facebook.yoga;
@@ -337,6 +338,47 @@ public class YGDisplayTest {
assertEquals(0f, root_child1.getLayoutHeight(), 0.0f); assertEquals(0f, root_child1.getLayoutHeight(), 0.0f);
} }
@Test
public void test_display_none_with_position_absolute() {
YogaConfig config = YogaConfigFactory.create();
final YogaNode root = createNode(config);
root.setWidth(100f);
root.setHeight(100f);
final YogaNode root_child0 = createNode(config);
root_child0.setPositionType(YogaPositionType.ABSOLUTE);
root_child0.setWidth(100f);
root_child0.setHeight(100f);
root_child0.setDisplay(YogaDisplay.NONE);
root.addChildAt(root_child0, 0);
root.setDirection(YogaDirection.LTR);
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
assertEquals(0f, root.getLayoutX(), 0.0f);
assertEquals(0f, root.getLayoutY(), 0.0f);
assertEquals(100f, root.getLayoutWidth(), 0.0f);
assertEquals(100f, root.getLayoutHeight(), 0.0f);
assertEquals(0f, root_child0.getLayoutX(), 0.0f);
assertEquals(0f, root_child0.getLayoutY(), 0.0f);
assertEquals(0f, root_child0.getLayoutWidth(), 0.0f);
assertEquals(0f, root_child0.getLayoutHeight(), 0.0f);
root.setDirection(YogaDirection.RTL);
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
assertEquals(0f, root.getLayoutX(), 0.0f);
assertEquals(0f, root.getLayoutY(), 0.0f);
assertEquals(100f, root.getLayoutWidth(), 0.0f);
assertEquals(100f, root.getLayoutHeight(), 0.0f);
assertEquals(0f, root_child0.getLayoutX(), 0.0f);
assertEquals(0f, root_child0.getLayoutY(), 0.0f);
assertEquals(0f, root_child0.getLayoutWidth(), 0.0f);
assertEquals(0f, root_child0.getLayoutHeight(), 0.0f);
}
private YogaNode createNode(YogaConfig config) { private YogaNode createNode(YogaConfig config) {
return mNodeFactory.create(config); return mNodeFactory.create(config);
} }

View File

@@ -9,10 +9,62 @@ package com.facebook.yoga;
import org.junit.Test; import org.junit.Test;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.List;
import java.util.ArrayList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
public class YogaLoggerTest { public class YogaLoggerTest {
@Test
public void testRemovingLoggerFromConfig() throws Exception {
final List<String> logs = new ArrayList<>();
final YogaConfig config = YogaConfigFactory.create();
YogaLogger logger = new YogaLogger() {
@Override
public void log(YogaLogLevel level, String message) {
logs.add(message);
}
};
config.setLogger(logger);
final YogaNode root = YogaNodeFactory.create(config);
root.setFlexDirection(YogaFlexDirection.ROW);
root.setAlignItems(YogaAlign.BASELINE);
final YogaNode child1 = YogaNodeFactory.create(config);
root.addChildAt(child1, 0);
final YogaNode child2 = YogaNodeFactory.create(config);
child2.setBaselineFunction(new YogaBaselineFunction() {
public float baseline(YogaNode node, float width, float height) {
return Float.NaN;
}
});
root.addChildAt(child2, 1);
assertEquals(logs.size(), 0);
try {
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
fail("Expected calculateLayout to throw");
} catch (IllegalStateException e) {
}
assertEquals(logs.size(), 1);
config.setLogger(null);
try {
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
fail("Expected calculateLayout to throw again");
} catch (IllegalStateException e) {
}
assertEquals(logs.size(), 1);
}
@Test @Test
public void testLoggerLeak() throws Exception { public void testLoggerLeak() throws Exception {
final YogaConfig config = YogaConfigFactory.create(); final YogaConfig config = YogaConfigFactory.create();

View File

@@ -191,7 +191,7 @@ public class YogaNodeStylePropertiesTest {
public void testPositionTypeDefault() { public void testPositionTypeDefault() {
final YogaNode node = createNode(); final YogaNode node = createNode();
assertEquals(YogaPositionType.RELATIVE, node.getPositionType()); assertEquals(YogaPositionType.STATIC, node.getPositionType());
} }
@Test @Test

View File

@@ -7,5 +7,9 @@
[lints] [lints]
[options] [options]
types_first=false
[strict] [strict]
[version]
^0.140.0

View File

@@ -23,8 +23,8 @@ static YGSize globalMeasureFunc(
Node const& node = *reinterpret_cast<Node const*>(YGNodeGetContext(nodeRef)); Node const& node = *reinterpret_cast<Node const*>(YGNodeGetContext(nodeRef));
Size size = node.callMeasureFunc(width, widthMode, height, heightMode); Size size = node.callMeasureFunc(width, widthMode, height, heightMode);
YGSize ygSize = {static_cast<float>(size.width), YGSize ygSize = {
static_cast<float>(size.height)}; static_cast<float>(size.width), static_cast<float>(size.height)};
return ygSize; return ygSize;
} }

View File

@@ -18,7 +18,5 @@ struct Size {
Size(double width, double height) : width(width), height(height) {} Size(double width, double height) : width(width), height(height) {}
void toJS(nbind::cbOutput expose) const { void toJS(nbind::cbOutput expose) const { expose(width, height); }
expose(width, height);
}
}; };

View File

@@ -21,7 +21,5 @@ struct Value {
Value(int unit, double value) : unit(unit), value(value) {} Value(int unit, double value) : unit(unit), value(value) {}
void toJS(nbind::cbOutput expose) const { void toJS(nbind::cbOutput expose) const { expose(unit, value); }
expose(unit, value);
}
}; };

View File

@@ -1,9 +1,10 @@
/** /**
* Copyright (c) Facebook, Inc. and its affiliates. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the LICENSE * This source code is licensed under the MIT license found in the
* file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// @Generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html // @Generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html
var Yoga = Yoga || require("../../sources/entry-" + process.env.TEST_ENTRY); var Yoga = Yoga || require("../../sources/entry-" + process.env.TEST_ENTRY);
@@ -342,3 +343,48 @@ it("display_none_with_position", function () {
config.free(); config.free();
} }
}); });
it("display_none_with_position_absolute", function () {
var config = Yoga.Config.create();
try {
var root = Yoga.Node.create(config);
root.setWidth(100);
root.setHeight(100);
var root_child0 = Yoga.Node.create(config);
root_child0.setPositionType(Yoga.POSITION_TYPE_ABSOLUTE);
root_child0.setWidth(100);
root_child0.setHeight(100);
root_child0.setDisplay(Yoga.DISPLAY_NONE);
root.insertChild(root_child0, 0);
root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR);
console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")");
console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")");
console.assert(100 === root.getComputedWidth(), "100 === root.getComputedWidth() (" + root.getComputedWidth() + ")");
console.assert(100 === root.getComputedHeight(), "100 === root.getComputedHeight() (" + root.getComputedHeight() + ")");
console.assert(0 === root_child0.getComputedLeft(), "0 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")");
console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")");
console.assert(0 === root_child0.getComputedWidth(), "0 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")");
console.assert(0 === root_child0.getComputedHeight(), "0 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")");
root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_RTL);
console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")");
console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")");
console.assert(100 === root.getComputedWidth(), "100 === root.getComputedWidth() (" + root.getComputedWidth() + ")");
console.assert(100 === root.getComputedHeight(), "100 === root.getComputedHeight() (" + root.getComputedHeight() + ")");
console.assert(0 === root_child0.getComputedLeft(), "0 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")");
console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")");
console.assert(0 === root_child0.getComputedWidth(), "0 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")");
console.assert(0 === root_child0.getComputedHeight(), "0 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")");
} finally {
if (typeof root !== "undefined") {
root.freeRecursive();
}
config.free();
}
});

View File

@@ -33,8 +33,8 @@ android {
} }
dependencies { dependencies {
implementation 'com.facebook.soloader:soloader:0.5.1' implementation 'com.facebook.soloader:soloader:0.10.1'
implementation 'com.google.code.findbugs:jsr305:3.0.1' implementation 'com.google.code.findbugs:jsr305:3.0.2'
implementation project(':yoga:proguard-annotations') implementation project(':yoga:proguard-annotations')
} }
} }

View File

@@ -3,7 +3,7 @@
# This source code is licensed under the MIT license found in the # This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree. # LICENSE file in the root directory of this source tree.
load("//tools/build_defs/oss:yoga_defs.bzl", "JSR_305_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "yoga_java_library") load("//tools/build_defs/oss:yoga_defs.bzl", "JSR_305_TARGET", "PROGUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "yoga_java_library")
yoga_java_library( yoga_java_library(
name = "jni", name = "jni",
@@ -13,7 +13,7 @@ yoga_java_library(
"PUBLIC", "PUBLIC",
], ],
deps = [ deps = [
PROGRUARD_ANNOTATIONS_TARGET, PROGUARD_ANNOTATIONS_TARGET,
SOLOADER_TARGET, SOLOADER_TARGET,
JSR_305_TARGET, JSR_305_TARGET,
], ],

View File

@@ -3,10 +3,9 @@
# This source code is licensed under the MIT license found in the # This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree. # LICENSE file in the root directory of this source tree.
load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS", "yoga_prebuilt_aar")
load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS")
fb_native.android_prebuilt_aar( yoga_prebuilt_aar(
name = "soloader", name = "soloader",
aar = "soloader-0.5.1.aar", aar = "soloader-0.5.1.aar",
visibility = YOGA_ROOTS, visibility = YOGA_ROOTS,

View File

@@ -14,17 +14,8 @@ set -e
BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
IS_SNAPSHOT="$(grep 'VERSION_NAME=[0-9\.]\+-SNAPSHOT' "$BASEDIR/gradle.properties")" IS_SNAPSHOT="$(grep 'VERSION_NAME=[0-9\.]\+-SNAPSHOT' "$BASEDIR/gradle.properties")"
if [ "$TRAVIS_REPO_SLUG" != "facebook/yoga" ]; then if [ "$IS_SNAPSHOT" == "" ]; then
echo >&2 "Skipping repository. Expected project to be 'facebook/yoga', but was '$TRAVIS_REPO_SLUG'."
exit
elif [ "$TRAVIS_BRANCH" != "master" ]; then
echo >&2 "Skipping build. Expected branch name to be 'master', but was '$TRAVIS_BRANCH'."
exit
elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
echo >&2 "Skipping build. Only considering non-PR builds, but URL was '$TRAVIS_PULL_REQUEST'."
exit
elif [ "$IS_SNAPSHOT" == "" ]; then
echo >&2 "Skipping build. Given build doesn't appear to be a SNAPSHOT release." echo >&2 "Skipping build. Given build doesn't appear to be a SNAPSHOT release."
else else
env TERMINAL=dumb "$BASEDIR/gradlew" uploadArchives env TERMINAL=dumb "$BASEDIR/gradlew" publish
fi fi

206
tests/BitUtilsTest.cpp Normal file
View File

@@ -0,0 +1,206 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include <cstdint>
#include <yoga/BitUtils.h>
namespace facebook {
namespace yoga {
TEST(BitUtils, one_boolean_defaults_to_false) {
constexpr uint8_t flags = 0;
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
static_assert(
detail::getBooleanData(flags, 0) == false,
"first boolean member must default to false");
}
TEST(BitUtils, one_boolean_can_be_initialized_to_true) {
constexpr uint8_t flags = 1;
ASSERT_EQ(detail::getBooleanData(flags, 0), true);
static_assert(
detail::getBooleanData(flags, 0) == true,
"first boolean member must be initialized to true");
}
TEST(BitUtils, one_boolean_can_be_set_to_true) {
uint8_t flags = 0;
detail::setBooleanData(flags, 0, true);
ASSERT_EQ(detail::getBooleanData(flags, 0), true);
}
TEST(BitUtils, second_boolean_defaults_to_false) {
constexpr uint8_t flags = 0;
ASSERT_EQ(detail::getBooleanData(flags, 1), false);
static_assert(
detail::getBooleanData(flags, 1) == false,
"second boolean member must default to false");
}
TEST(BitUtils, second_boolean_can_be_initialized_to_true) {
constexpr uint8_t flags = 2;
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
ASSERT_EQ(detail::getBooleanData(flags, 1), true);
static_assert(
detail::getBooleanData(flags, 0) == false,
"first boolean member must default to false");
static_assert(
detail::getBooleanData(flags, 1) == true,
"second boolean member must be initialized to true");
}
TEST(BitUtils, second_boolean_can_be_set_to_true) {
uint8_t flags = 0;
detail::setBooleanData(flags, 1, true);
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
ASSERT_EQ(detail::getBooleanData(flags, 1), true);
}
TEST(BitUtils, third_boolean_defaults_to_false) {
constexpr uint8_t flags = 0;
ASSERT_EQ(detail::getBooleanData(flags, 2), false);
static_assert(
detail::getBooleanData(flags, 2) == false,
"second boolean member must default to false");
}
TEST(BitUtils, third_boolean_can_be_initialized_to_true) {
constexpr uint8_t flags = 4;
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
ASSERT_EQ(detail::getBooleanData(flags, 1), false);
ASSERT_EQ(detail::getBooleanData(flags, 2), true);
static_assert(
detail::getBooleanData(flags, 0) == false,
"first boolean member must default to false");
static_assert(
detail::getBooleanData(flags, 1) == false,
"second boolean member must default to false");
static_assert(
detail::getBooleanData(flags, 2) == true,
"second boolean member must be initialized to true");
}
TEST(BitUtils, third_boolean_can_be_set_to_true) {
uint8_t flags = 0;
detail::setBooleanData(flags, 2, true);
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
ASSERT_EQ(detail::getBooleanData(flags, 1), false);
ASSERT_EQ(detail::getBooleanData(flags, 2), true);
}
TEST(BitUtils, setting_boolean_values_does_not_spill_over) {
uint8_t flags = 0;
detail::setBooleanData(flags, 1, (bool) 7);
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
ASSERT_EQ(detail::getBooleanData(flags, 1), true);
ASSERT_EQ(detail::getBooleanData(flags, 2), false);
}
TEST(BitUtils, first_enum_defaults_to_0) {
constexpr uint8_t flags = 0;
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, 0), YGAlignAuto);
static_assert(
detail::getEnumData<YGAlign>(flags, 0) == YGAlignAuto,
"first enum member must default to 0");
}
TEST(BitUtils, first_enum_can_be_set) {
uint8_t flags = 0;
detail::setEnumData<YGAlign>(flags, 0, YGAlignSpaceBetween);
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, 0), YGAlignSpaceBetween);
}
TEST(BitUtils, second_enum_defaults_to_0) {
constexpr uint8_t flags = 0;
static constexpr size_t alignOffset = 0;
static constexpr size_t edgeOffset = 3;
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, alignOffset), YGAlignAuto);
ASSERT_EQ(detail::getEnumData<YGEdge>(flags, edgeOffset), YGEdgeLeft);
static_assert(
detail::getEnumData<YGAlign>(flags, alignOffset) == YGAlignAuto,
"first enum member must default to 0");
static_assert(
detail::getEnumData<YGEdge>(flags, edgeOffset) == YGEdgeLeft,
"second enum member must default to 0");
}
TEST(BitUtils, second_enum_can_be_set) {
uint8_t flags = 0;
static constexpr size_t alignOffset = 0;
static constexpr size_t edgeOffset = 3;
detail::setEnumData<YGEdge>(flags, edgeOffset, YGEdgeAll);
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, alignOffset), YGAlignAuto);
ASSERT_EQ(detail::getEnumData<YGEdge>(flags, edgeOffset), YGEdgeAll);
}
TEST(BitUtils, third_enum_defaults_to_0) {
constexpr uint8_t flags = 0;
static constexpr size_t alignOffset = 0;
static constexpr size_t boolOffset = 3;
static constexpr size_t edgesOffset = 4;
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, alignOffset), YGAlignAuto);
ASSERT_EQ(detail::getBooleanData(flags, boolOffset), false);
ASSERT_EQ(detail::getEnumData<YGEdge>(flags, edgesOffset), YGEdgeLeft);
static_assert(
detail::getEnumData<YGAlign>(flags, alignOffset) == YGAlignAuto,
"first enum member must default to 0");
static_assert(
detail::getBooleanData(flags, boolOffset) == false,
"middle boolean member must default to false");
static_assert(
detail::getEnumData<YGEdge>(flags, edgesOffset) == YGEdgeLeft,
"last enum member must default to 0");
}
TEST(BitUtils, third_enum_can_be_set) {
uint8_t flags = 0;
static constexpr size_t alignOffset = 0;
static constexpr size_t boolOffset = 3;
static constexpr size_t edgesOffset = 4;
detail::setEnumData<YGEdge>(flags, edgesOffset, YGEdgeVertical);
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, alignOffset), YGAlignAuto);
ASSERT_EQ(detail::getBooleanData(flags, boolOffset), false);
ASSERT_EQ(detail::getEnumData<YGEdge>(flags, edgesOffset), YGEdgeVertical);
}
TEST(BitUtils, setting_values_does_not_spill_over) {
uint8_t flags = 0;
static constexpr size_t alignOffset = 0;
static constexpr size_t edgesOffset = 3;
static constexpr size_t boolOffset = 7;
detail::setEnumData<YGEdge>(flags, edgesOffset, (YGEdge) 0xffffff);
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, alignOffset), 0);
ASSERT_EQ(detail::getBooleanData(flags, boolOffset), false);
ASSERT_EQ(detail::getEnumData<YGEdge>(flags, edgesOffset), 0xf);
}
} // namespace yoga
} // namespace facebook

View File

@@ -1,244 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include <cstdint>
#include <yoga/Bitfield.h>
namespace facebook {
namespace yoga {
TEST(Bitfield, one_boolean_defaults_to_false) {
constexpr auto bf = Bitfield<uint8_t, bool>{};
ASSERT_EQ(bf.at<0>(), false);
static_assert(
bf.at<0>() == false, "first boolean member must default to false");
}
TEST(Bitfield, one_boolean_can_be_initialized_to_true) {
constexpr auto bf = Bitfield<uint8_t, bool>{true};
ASSERT_EQ(bf.at<0>(), true);
static_assert(
bf.at<0>() == true, "first boolean member must be initialized to true");
}
TEST(Bitfield, one_boolean_can_be_set_to_true) {
auto bf = Bitfield<uint8_t, bool>{};
bf.at<0>() = true;
ASSERT_EQ(bf.at<0>(), true);
}
TEST(Bitfield, second_boolean_defaults_to_false) {
constexpr auto bf = Bitfield<uint8_t, bool, bool>{};
ASSERT_EQ(bf.at<1>(), false);
static_assert(
bf.at<1>() == false, "second boolean member must default to false");
}
TEST(Bitfield, second_boolean_can_be_initialized_to_true) {
constexpr auto bf = Bitfield<uint8_t, bool, bool>{false, true};
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), true);
static_assert(
bf.at<0>() == false, "first boolean member must default to false");
static_assert(
bf.at<1>() == true, "second boolean member must be initialized to true");
}
TEST(Bitfield, second_boolean_can_be_set_to_true) {
auto bf = Bitfield<uint8_t, bool, bool>{};
bf.at<1>() = true;
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), true);
}
TEST(Bitfield, third_boolean_defaults_to_false) {
constexpr auto bf = Bitfield<uint8_t, bool, bool, bool>{};
ASSERT_EQ(bf.at<2>(), false);
static_assert(
bf.at<2>() == false, "second boolean member must default to false");
}
TEST(Bitfield, third_boolean_can_be_initialized_to_true) {
constexpr auto bf = Bitfield<uint8_t, bool, bool, bool>{false, false, true};
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), false);
ASSERT_EQ(bf.at<2>(), true);
static_assert(
bf.at<0>() == false, "first boolean member must default to false");
static_assert(
bf.at<1>() == false, "second boolean member must default to false");
static_assert(
bf.at<2>() == true, "second boolean member must be initialized to true");
}
TEST(Bitfield, third_boolean_can_be_set_to_true) {
auto bf = Bitfield<uint8_t, bool, bool, bool>{};
bf.at<2>() = true;
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), false);
ASSERT_EQ(bf.at<2>(), true);
}
TEST(Bitfield, initializing_boolean_values_does_not_spill_over) {
constexpr auto bf =
Bitfield<uint8_t, bool, bool, bool>{false, (bool) 7, false};
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), true);
ASSERT_EQ(bf.at<2>(), false);
static_assert(
bf.at<0>() == false, "first boolean member must be initialized to false");
static_assert(
bf.at<1>() == true, "second boolean member must be initialized to true");
static_assert(
bf.at<2>() == false, "third boolean member must be initialized to false");
}
TEST(Bitfield, setting_boolean_values_does_not_spill_over) {
auto bf = Bitfield<uint8_t, bool, bool, bool>{};
bf.at<1>() = (bool) 7;
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), true);
ASSERT_EQ(bf.at<2>(), false);
}
TEST(Bitfield, first_enum_defaults_to_0) {
constexpr auto bf = Bitfield<uint8_t, YGAlign>{};
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
static_assert(
bf.at<0>() == YGAlignAuto, "first enum member must default to 0");
}
TEST(Bitfield, first_enum_can_be_initialized) {
constexpr auto bf = Bitfield<uint8_t, YGAlign>{YGAlignFlexEnd};
ASSERT_EQ(bf.at<0>(), YGAlignFlexEnd);
static_assert(
bf.at<0>() == YGAlignFlexEnd,
"first enum member must be initialized to YGAlignFlexEnd");
}
TEST(Bitfield, first_enum_can_be_set) {
auto bf = Bitfield<uint8_t, YGAlign>{};
bf.at<0>() = YGAlignSpaceBetween;
ASSERT_EQ(bf.at<0>(), YGAlignSpaceBetween);
}
TEST(Bitfield, second_enum_defaults_to_0) {
constexpr auto bf = Bitfield<uint8_t, YGAlign, YGEdge>{};
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), YGEdgeLeft);
static_assert(
bf.at<0>() == YGAlignAuto, "first enum member must default to 0");
static_assert(
bf.at<1>() == YGEdgeLeft, "second enum member must default to 0");
}
TEST(Bitfield, second_enum_can_be_initialized) {
constexpr auto bf =
Bitfield<uint8_t, YGAlign, YGEdge>{YGAlignAuto, YGEdgeAll};
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), YGEdgeAll);
static_assert(
bf.at<0>() == YGAlignAuto, "first enum member must default to 0");
static_assert(
bf.at<1>() == YGEdgeAll,
"second enum member must be initialized to YGEdgeAll");
}
TEST(Bitfield, second_enum_can_be_set) {
auto bf = Bitfield<uint8_t, YGAlign, YGEdge>{};
bf.at<1>() = YGEdgeAll;
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), YGEdgeAll);
}
TEST(Bitfield, third_enum_defaults_to_0) {
constexpr auto bf = Bitfield<uint8_t, YGAlign, bool, YGEdge>{};
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), false);
ASSERT_EQ(bf.at<2>(), YGEdgeLeft);
static_assert(
bf.at<0>() == YGAlignAuto, "first enum member must default to 0");
static_assert(
bf.at<1>() == false, "middle boolean member must default to false");
static_assert(bf.at<2>() == YGEdgeLeft, "last enum member must default to 0");
}
TEST(Bitfield, third_enum_can_be_initialized) {
constexpr auto bf = Bitfield<uint8_t, YGAlign, bool, YGEdge>{
YGAlignAuto, false, YGEdgeVertical};
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), false);
ASSERT_EQ(bf.at<2>(), YGEdgeVertical);
static_assert(
bf.at<0>() == YGAlignAuto, "first enum member must default to 0");
static_assert(
bf.at<1>() == false, "middle boolean member must default to false");
static_assert(
bf.at<2>() == YGEdgeVertical,
"second enum member must be initialized to YGEdgeVertical");
}
TEST(Bitfield, third_enum_can_be_set) {
auto bf = Bitfield<uint8_t, YGAlign, bool, YGEdge>{};
bf.at<2>() = YGEdgeVertical;
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), false);
ASSERT_EQ(bf.at<2>(), YGEdgeVertical);
}
TEST(Bitfield, initializing_values_does_not_spill_over) {
constexpr auto bf = Bitfield<uint8_t, YGAlign, YGEdge, bool>{
(YGAlign) 0, (YGEdge) 0xffffff, false};
ASSERT_EQ(bf.at<0>(), (YGAlign) 0);
ASSERT_EQ(bf.at<1>(), 0xf);
ASSERT_EQ(bf.at<2>(), false);
static_assert(bf.at<0>() == 0, "first enum member must be initialized to 0");
static_assert(
bf.at<1>() == 0xf, "second member must be initialized to YGEdgeVertical");
static_assert(
bf.at<2>() == false, "boolean member must be initialized to false");
}
TEST(Bitfield, setting_values_does_not_spill_over) {
auto bf = Bitfield<uint8_t, YGAlign, YGEdge, bool>{};
bf.at<1>() = (YGEdge) 0xffffff;
ASSERT_EQ(bf.at<0>(), 0);
ASSERT_EQ(bf.at<1>(), 0xf);
ASSERT_EQ(bf.at<2>(), false);
}
} // namespace yoga
} // namespace facebook

View File

@@ -303,8 +303,8 @@ EventArgs createArgs(
}; };
EventArgs args = createArgs<E>(node, data); EventArgs args = createArgs<E>(node, data);
args.eventTestDataPtr = {new EventTestData{eventTestData}, args.eventTestDataPtr = {
deleteEventTestData}; new EventTestData{eventTestData}, deleteEventTestData};
return args; return args;
} }

View File

@@ -29,12 +29,13 @@ TEST(YogaTest, computed_layout_margin) {
} }
TEST(YogaTest, margin_side_overrides_horizontal_and_vertical) { TEST(YogaTest, margin_side_overrides_horizontal_and_vertical) {
const std::array<YGEdge, 6> edges = {{YGEdgeTop, const std::array<YGEdge, 6> edges = {
YGEdgeBottom, {YGEdgeTop,
YGEdgeStart, YGEdgeBottom,
YGEdgeEnd, YGEdgeStart,
YGEdgeLeft, YGEdgeEnd,
YGEdgeRight}}; YGEdgeLeft,
YGEdgeRight}};
for (float edgeValue = 0; edgeValue < 2; ++edgeValue) { for (float edgeValue = 0; edgeValue < 2; ++edgeValue) {
for (const auto& edge : edges) { for (const auto& edge : edges) {
@@ -58,12 +59,13 @@ TEST(YogaTest, margin_side_overrides_horizontal_and_vertical) {
} }
TEST(YogaTest, margin_side_overrides_all) { TEST(YogaTest, margin_side_overrides_all) {
const std::array<YGEdge, 6> edges = {{YGEdgeTop, const std::array<YGEdge, 6> edges = {
YGEdgeBottom, {YGEdgeTop,
YGEdgeStart, YGEdgeBottom,
YGEdgeEnd, YGEdgeStart,
YGEdgeLeft, YGEdgeEnd,
YGEdgeRight}}; YGEdgeLeft,
YGEdgeRight}};
for (float edgeValue = 0; edgeValue < 2; ++edgeValue) { for (float edgeValue = 0; edgeValue < 2; ++edgeValue) {
for (const auto& edge : edges) { for (const auto& edge : edges) {

View File

@@ -29,12 +29,13 @@ TEST(YogaTest, computed_layout_padding) {
} }
TEST(YogaTest, padding_side_overrides_horizontal_and_vertical) { TEST(YogaTest, padding_side_overrides_horizontal_and_vertical) {
const std::array<YGEdge, 6> edges = {{YGEdgeTop, const std::array<YGEdge, 6> edges = {
YGEdgeBottom, {YGEdgeTop,
YGEdgeStart, YGEdgeBottom,
YGEdgeEnd, YGEdgeStart,
YGEdgeLeft, YGEdgeEnd,
YGEdgeRight}}; YGEdgeLeft,
YGEdgeRight}};
for (float edgeValue = 0; edgeValue < 2; ++edgeValue) { for (float edgeValue = 0; edgeValue < 2; ++edgeValue) {
for (const auto& edge : edges) { for (const auto& edge : edges) {
@@ -58,12 +59,13 @@ TEST(YogaTest, padding_side_overrides_horizontal_and_vertical) {
} }
TEST(YogaTest, padding_side_overrides_all) { TEST(YogaTest, padding_side_overrides_all) {
const std::array<YGEdge, 6> edges = {{YGEdgeTop, const std::array<YGEdge, 6> edges = {
YGEdgeBottom, {YGEdgeTop,
YGEdgeStart, YGEdgeBottom,
YGEdgeEnd, YGEdgeStart,
YGEdgeLeft, YGEdgeEnd,
YGEdgeRight}}; YGEdgeLeft,
YGEdgeRight}};
for (float edgeValue = 0; edgeValue < 2; ++edgeValue) { for (float edgeValue = 0; edgeValue < 2; ++edgeValue) {
for (const auto& edge : edges) { for (const auto& edge : edges) {

View File

@@ -20,7 +20,7 @@ TEST(YogaTest, assert_default_values) {
ASSERT_EQ(YGAlignFlexStart, YGNodeStyleGetAlignContent(root)); ASSERT_EQ(YGAlignFlexStart, YGNodeStyleGetAlignContent(root));
ASSERT_EQ(YGAlignStretch, YGNodeStyleGetAlignItems(root)); ASSERT_EQ(YGAlignStretch, YGNodeStyleGetAlignItems(root));
ASSERT_EQ(YGAlignAuto, YGNodeStyleGetAlignSelf(root)); ASSERT_EQ(YGAlignAuto, YGNodeStyleGetAlignSelf(root));
ASSERT_EQ(YGPositionTypeRelative, YGNodeStyleGetPositionType(root)); ASSERT_EQ(YGPositionTypeStatic, YGNodeStyleGetPositionType(root));
ASSERT_EQ(YGWrapNoWrap, YGNodeStyleGetFlexWrap(root)); ASSERT_EQ(YGWrapNoWrap, YGNodeStyleGetFlexWrap(root));
ASSERT_EQ(YGOverflowVisible, YGNodeStyleGetOverflow(root)); ASSERT_EQ(YGOverflowVisible, YGNodeStyleGetOverflow(root));
ASSERT_FLOAT_EQ(0, YGNodeStyleGetFlexGrow(root)); ASSERT_FLOAT_EQ(0, YGNodeStyleGetFlexGrow(root));

View File

@@ -1,9 +1,10 @@
/* /*
* Copyright (c) Facebook, Inc. and its affiliates. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the LICENSE * This source code is licensed under the MIT license found in the
* file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// @Generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html // @Generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html
#include <gtest/gtest.h> #include <gtest/gtest.h>
@@ -327,3 +328,45 @@ TEST(YogaTest, display_none_with_position) {
YGConfigFree(config); YGConfigFree(config);
} }
TEST(YogaTest, display_none_with_position_absolute) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root, 100);
YGNodeStyleSetHeight(root, 100);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeStyleSetDisplay(root_child0, YGDisplayNone);
YGNodeInsertChild(root, root_child0, 0);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}

View File

@@ -605,3 +605,121 @@ TEST(YogaTest, flex_grow_less_than_factor_one) {
YGConfigFree(config); YGConfigFree(config);
} }
TEST(YogaTest, flex_shrink_min_width) {
const YGConfigRef config = YGConfigNew();
YGConfigSetUseWebDefaults(config, true);
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetMinWidth(root_child0, 301);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow);
YGNodeStyleSetWidth(root_child1, 100);
YGNodeStyleSetMinWidth(root_child1, 25);
YGNodeStyleSetHeight(root_child1, 100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child2, YGFlexDirectionRow);
YGNodeStyleSetWidth(root_child2, 100);
YGNodeStyleSetHeight(root_child2, 100);
YGNodeInsertChild(root, root_child2, 2);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(301, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(301, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(401, YGNodeLayoutGetLeft(root_child2));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
ASSERT_FLOAT_EQ(99, YGNodeLayoutGetWidth(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(YogaTest, flex_shrink_flex_grow_min_width) {
const YGConfigRef config = YGConfigNew();
YGConfigSetUseWebDefaults(config, true);
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
YGNodeStyleSetFlexGrow(root_child0, 0);
YGNodeStyleSetFlexShrink(root_child0, 1);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetMinWidth(root_child0, 301);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow);
YGNodeStyleSetFlexGrow(root_child1, 1);
YGNodeStyleSetFlexShrink(root_child1, 1);
YGNodeStyleSetWidth(root_child1, 100);
YGNodeStyleSetMinWidth(root_child1, 25);
YGNodeStyleSetHeight(root_child1, 100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child2, YGFlexDirectionRow);
YGNodeStyleSetWidth(root_child2, 100);
YGNodeStyleSetHeight(root_child2, 100);
YGNodeStyleSetFlexShrink(root_child2, 1);
YGNodeStyleSetFlexGrow(root_child2, 1);
YGNodeInsertChild(root, root_child2, 2);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(301, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(301, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(401, YGNodeLayoutGetLeft(root_child2));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
ASSERT_FLOAT_EQ(99, YGNodeLayoutGetWidth(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}

View File

@@ -73,8 +73,7 @@ TEST(YogaTest, logger_default_node_should_print_no_style_info) {
YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR); YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR);
YGNodePrint( YGNodePrint(
root, root,
(YGPrintOptions)( (YGPrintOptions) (YGPrintOptionsLayout | YGPrintOptionsChildren | YGPrintOptionsStyle));
YGPrintOptionsLayout | YGPrintOptionsChildren | YGPrintOptionsStyle));
YGConfigSetLogger(config, NULL); YGConfigSetLogger(config, NULL);
YGNodeFree(root); YGNodeFree(root);
@@ -98,8 +97,7 @@ TEST(YogaTest, logger_node_with_percentage_absolute_position_and_margin) {
YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR); YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR);
YGNodePrint( YGNodePrint(
root, root,
(YGPrintOptions)( (YGPrintOptions) (YGPrintOptionsLayout | YGPrintOptionsChildren | YGPrintOptionsStyle));
YGPrintOptionsLayout | YGPrintOptionsChildren | YGPrintOptionsStyle));
YGConfigSetLogger(config, NULL); YGConfigSetLogger(config, NULL);
YGNodeFree(root); YGNodeFree(root);
@@ -122,8 +120,7 @@ TEST(YogaTest, logger_node_with_children_should_print_indented) {
YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR); YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR);
YGNodePrint( YGNodePrint(
root, root,
(YGPrintOptions)( (YGPrintOptions) (YGPrintOptionsLayout | YGPrintOptionsChildren | YGPrintOptionsStyle));
YGPrintOptionsLayout | YGPrintOptionsChildren | YGPrintOptionsStyle));
YGConfigSetLogger(config, NULL); YGConfigSetLogger(config, NULL);
YGNodeFreeRecursive(root); YGNodeFreeRecursive(root);

View File

@@ -580,7 +580,7 @@ TEST(YogaDeathTest, cannot_add_child_to_node_with_measure_func) {
root->setMeasureFunc(_measure); root->setMeasureFunc(_measure);
const YGNodeRef root_child0 = YGNodeNew(); const YGNodeRef root_child0 = YGNodeNew();
ASSERT_DEATH(YGNodeInsertChild(root, root_child0, 0), "Cannot add child.*"); ASSERT_THROW(YGNodeInsertChild(root, root_child0, 0), std::logic_error);
YGNodeFree(root_child0); YGNodeFree(root_child0);
YGNodeFreeRecursive(root); YGNodeFreeRecursive(root);
} }
@@ -589,7 +589,7 @@ TEST(YogaDeathTest, cannot_add_nonnull_measure_func_to_non_leaf_node) {
const YGNodeRef root = YGNodeNew(); const YGNodeRef root = YGNodeNew();
const YGNodeRef root_child0 = YGNodeNew(); const YGNodeRef root_child0 = YGNodeNew();
YGNodeInsertChild(root, root_child0, 0); YGNodeInsertChild(root, root_child0, 0);
ASSERT_DEATH(root->setMeasureFunc(_measure), "Cannot set measure function.*"); ASSERT_THROW(root->setMeasureFunc(_measure), std::logic_error);
YGNodeFreeRecursive(root); YGNodeFreeRecursive(root);
} }
@@ -654,6 +654,19 @@ static YGSize _measure_90_10(
}; };
} }
static YGSize _measure_100_100(
YGNodeRef node,
float width,
YGMeasureMode widthMode,
float height,
YGMeasureMode heightMode) {
return YGSize{
.width = 100,
.height = 100,
};
}
TEST(YogaTest, percent_with_text_node) { TEST(YogaTest, percent_with_text_node) {
const YGConfigRef config = YGConfigNew(); const YGConfigRef config = YGConfigNew();
@@ -686,9 +699,211 @@ TEST(YogaTest, percent_with_text_node) {
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1)); ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(15, YGNodeLayoutGetTop(root_child1)); ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1)); ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(YogaTest, percent_margin_with_measure_func) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeStyleSetMargin(root_child0, YGEdgeTop, 0);
root_child0->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child1, 100);
YGNodeStyleSetHeight(root_child1, 100);
YGNodeStyleSetMargin(root_child1, YGEdgeTop, 100);
root_child1->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child2, 100);
YGNodeStyleSetHeight(root_child2, 100);
YGNodeStyleSetMarginPercent(root_child2, YGEdgeTop, 10);
root_child2->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child2, 2);
const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child3, 100);
YGNodeStyleSetHeight(root_child3, 100);
YGNodeStyleSetMarginPercent(root_child3, YGEdgeTop, 20);
root_child3->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child3, 3);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child2));
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(YogaTest, percent_padding_with_measure_func) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
YGNodeStyleSetAlignContent(root, YGAlignFlexStart);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeStyleSetPadding(root_child0, YGEdgeTop, 0);
root_child0->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child1, 100);
YGNodeStyleSetHeight(root_child1, 100);
YGNodeStyleSetPadding(root_child1, YGEdgeTop, 100);
root_child1->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
YGNodeStyleSetPaddingPercent(root_child2, YGEdgeTop, 10);
root_child2->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child2, 2);
const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
YGNodeStyleSetPaddingPercent(root_child3, YGEdgeTop, 20);
root_child3->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child3, 3);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child2));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child2));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child3));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child3));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(YogaTest, percent_padding_and_percent_margin_with_measure_func) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
YGNodeStyleSetAlignContent(root, YGAlignFlexStart);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeStyleSetPadding(root_child0, YGEdgeTop, 0);
root_child0->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child1, 100);
YGNodeStyleSetHeight(root_child1, 100);
YGNodeStyleSetPadding(root_child1, YGEdgeTop, 100);
root_child1->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
YGNodeStyleSetPaddingPercent(root_child2, YGEdgeTop, 10);
YGNodeStyleSetMarginPercent(root_child2, YGEdgeTop, 10);
root_child2->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child2, 2);
const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
YGNodeStyleSetPaddingPercent(root_child3, YGEdgeTop, 20);
YGNodeStyleSetMarginPercent(root_child3, YGEdgeTop, 20);
root_child3->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child3, 3);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child2));
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child2));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child3));
YGNodeFreeRecursive(root); YGNodeFreeRecursive(root);

View File

@@ -132,9 +132,10 @@ ACCESSOR_TEST(
ACCESSOR_TEST( ACCESSOR_TEST(
positionType, positionType,
YGPositionTypeRelative, YGPositionTypeStatic,
YGPositionTypeAbsolute, YGPositionTypeAbsolute,
YGPositionTypeRelative) YGPositionTypeRelative,
YGPositionTypeStatic)
ACCESSOR_TEST( ACCESSOR_TEST(
flexWrap, flexWrap,

View File

@@ -29,8 +29,8 @@ TEST(YogaTest, set_children_adds_children_to_parent) {
const std::vector<YGNodeRef> expectedChildren = {root_child0, root_child1}; const std::vector<YGNodeRef> expectedChildren = {root_child0, root_child1};
ASSERT_EQ(children, expectedChildren); ASSERT_EQ(children, expectedChildren);
const std::vector<YGNodeRef> owners = {YGNodeGetOwner(root_child0), const std::vector<YGNodeRef> owners = {
YGNodeGetOwner(root_child1)}; YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)};
const std::vector<YGNodeRef> expectedOwners = {root, root}; const std::vector<YGNodeRef> expectedOwners = {root, root};
ASSERT_EQ(owners, expectedOwners); ASSERT_EQ(owners, expectedOwners);
@@ -49,8 +49,8 @@ TEST(YogaTest, set_children_to_empty_removes_old_children) {
const std::vector<YGNodeRef> expectedChildren = {}; const std::vector<YGNodeRef> expectedChildren = {};
ASSERT_EQ(children, expectedChildren); ASSERT_EQ(children, expectedChildren);
const std::vector<YGNodeRef> owners = {YGNodeGetOwner(root_child0), const std::vector<YGNodeRef> owners = {
YGNodeGetOwner(root_child1)}; YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)};
const std::vector<YGNodeRef> expectedOwners = {nullptr, nullptr}; const std::vector<YGNodeRef> expectedOwners = {nullptr, nullptr};
ASSERT_EQ(owners, expectedOwners); ASSERT_EQ(owners, expectedOwners);
@@ -73,8 +73,8 @@ TEST(YogaTest, set_children_replaces_non_common_children) {
const std::vector<YGNodeRef> expectedChildren = {root_child2, root_child3}; const std::vector<YGNodeRef> expectedChildren = {root_child2, root_child3};
ASSERT_EQ(children, expectedChildren); ASSERT_EQ(children, expectedChildren);
const std::vector<YGNodeRef> owners = {YGNodeGetOwner(root_child0), const std::vector<YGNodeRef> owners = {
YGNodeGetOwner(root_child1)}; YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)};
const std::vector<YGNodeRef> expectedOwners = {nullptr, nullptr}; const std::vector<YGNodeRef> expectedOwners = {nullptr, nullptr};
ASSERT_EQ(owners, expectedOwners); ASSERT_EQ(owners, expectedOwners);
@@ -100,10 +100,11 @@ TEST(YogaTest, set_children_keeps_and_reorders_common_children) {
root_child2, root_child1, root_child3}; root_child2, root_child1, root_child3};
ASSERT_EQ(children, expectedChildren); ASSERT_EQ(children, expectedChildren);
const std::vector<YGNodeRef> owners = {YGNodeGetOwner(root_child0), const std::vector<YGNodeRef> owners = {
YGNodeGetOwner(root_child1), YGNodeGetOwner(root_child0),
YGNodeGetOwner(root_child2), YGNodeGetOwner(root_child1),
YGNodeGetOwner(root_child3)}; YGNodeGetOwner(root_child2),
YGNodeGetOwner(root_child3)};
const std::vector<YGNodeRef> expectedOwners = {nullptr, root, root, root}; const std::vector<YGNodeRef> expectedOwners = {nullptr, root, root, root};
ASSERT_EQ(owners, expectedOwners); ASSERT_EQ(owners, expectedOwners);

Some files were not shown because too many files have changed in this diff Show More