Compare commits
195 Commits
v2016.12.05.00
...
1.2.0
Author | SHA1 | Date | |
---|---|---|---|
|
4f5c7ed6af | ||
|
60ffa1953b | ||
|
5519a73087 | ||
|
67717a7872 | ||
|
4522d4b8aa | ||
|
d7ca339c27 | ||
|
6b39165801 | ||
|
78ade6cfb5 | ||
|
3f68b4f76b | ||
|
521aab5fcc | ||
|
42492596b3 | ||
|
b24e728666 | ||
|
4fe0b810e1 | ||
|
8deed174f5 | ||
|
2184547094 | ||
|
8eda4dc040 | ||
|
4d4db92a46 | ||
|
ea8b7e0c91 | ||
|
6928957096 | ||
|
b680b726d1 | ||
|
fbd692c449 | ||
|
2199a7908d | ||
|
59704f1508 | ||
|
20536923d6 | ||
|
bba7289537 | ||
|
04d1ccc085 | ||
|
a7e7c5eb52 | ||
|
9d2839f8ca | ||
|
1146013e9e | ||
|
8a91c0a0e5 | ||
|
a1c75454e9 | ||
|
ad3963daa6 | ||
|
a66339d63c | ||
|
d0bdd4dc91 | ||
|
d24078be31 | ||
|
f251648726 | ||
|
b587ecb30f | ||
|
a580712b2f | ||
|
ce5d52b54e | ||
|
55fe6f0bc9 | ||
|
abf142ea3f | ||
|
ae9f89b5d1 | ||
|
058761e16e | ||
|
ad8c6225fd | ||
|
1cbadf5f54 | ||
|
e7021715b8 | ||
|
0d2749a3fd | ||
|
76fbd628e1 | ||
|
15309d2bdd | ||
|
4f6924a0c1 | ||
|
063f65d065 | ||
|
adf8691093 | ||
|
6a7ad2125d | ||
|
247aa26d3e | ||
|
3c9f620c77 | ||
|
e0e2a61dfc | ||
|
168ae4099d | ||
|
6ceb4af2d4 | ||
|
240c2dd657 | ||
|
a5b94ebd0c | ||
|
5037c2f365 | ||
|
ef05404bee | ||
|
3db493665e | ||
|
737f1cc67c | ||
|
b5c2b09780 | ||
|
46817a38c3 | ||
|
52f3471405 | ||
|
e567502750 | ||
|
c1cdc1de58 | ||
|
f2c41f366f | ||
|
56d06e27cf | ||
|
93e327f4a5 | ||
|
687668a4b3 | ||
|
cfeac79130 | ||
|
4227e36ca5 | ||
|
be1c9f249e | ||
|
511a129a7e | ||
|
d62ca8c518 | ||
|
30413265c7 | ||
|
bd5d8a77c9 | ||
|
326ae15532 | ||
|
9afb65da34 | ||
|
fe7643c84a | ||
|
6daad3ae66 | ||
|
44590b8907 | ||
|
4400b52aab | ||
|
c217553cf8 | ||
|
6ad5003149 | ||
|
7c77b0e48c | ||
|
7b36118df4 | ||
|
7f0dbe5356 | ||
|
b87fc217df | ||
|
625dc4bf44 | ||
|
34736a4929 | ||
|
4f37cde043 | ||
|
7df60376ff | ||
|
7fa4adb0d9 | ||
|
abb91ae77b | ||
|
a4b1ac83f4 | ||
|
8775cdc13f | ||
|
db732ce9fa | ||
|
7c09244c39 | ||
|
2cc2a5f2ff | ||
|
e4b50f2a8d | ||
|
a2a84532ff | ||
|
d391323129 | ||
|
ab28ecf31b | ||
|
a4bab68802 | ||
|
e3cfacf0cb | ||
|
8d74e01f41 | ||
|
5404bb13d4 | ||
|
be8773fee0 | ||
|
0bcec80dfe | ||
|
2c8c2bffda | ||
|
d70f289e73 | ||
|
498a5980e8 | ||
|
8021c5d968 | ||
|
c536ab214d | ||
|
adb81e2a1e | ||
|
c4a3e12add | ||
|
a3d7d72421 | ||
|
47266b9ae8 | ||
|
e39f13a8ea | ||
|
c04604dbc0 | ||
|
1782646723 | ||
|
78e64e3d5b | ||
|
0acb620159 | ||
|
9982295e10 | ||
|
8ed71b2777 | ||
|
969b3709db | ||
|
e2a7938b26 | ||
|
70a4221b9e | ||
|
8d320ceac2 | ||
|
c169a98be6 | ||
|
6d48307c8d | ||
|
e539ecc9aa | ||
|
bf5eeaf61e | ||
|
a36faf89e3 | ||
|
29c44e281c | ||
|
1877a97898 | ||
|
bf6602ebff | ||
|
6bcf0e3a50 | ||
|
d0aeabb8f0 | ||
|
956df20c64 | ||
|
7108454455 | ||
|
663a93912b | ||
|
a85bd4ad2a | ||
|
6f462a72bf | ||
|
352f592767 | ||
|
f2080e520f | ||
|
cd78291de5 | ||
|
ab595d1875 | ||
|
597544e30a | ||
|
9f59a13836 | ||
|
12017e49bd | ||
|
abad796c44 | ||
|
92137273a2 | ||
|
f1ab289022 | ||
|
a302b76d59 | ||
|
4717594e93 | ||
|
df0f76bba5 | ||
|
e43c9f66ff | ||
|
0df58d8aa2 | ||
|
ff1a0e1eb8 | ||
|
ed765fe508 | ||
|
1b5eb7da5e | ||
|
071f576db9 | ||
|
3d10ba5f72 | ||
|
85b8386ba1 | ||
|
7ec3607446 | ||
|
835bb1cd9c | ||
|
9d35dce63e | ||
|
74fb205083 | ||
|
ba0bb10366 | ||
|
0296511f2c | ||
|
04fe81f88f | ||
|
98bbc15435 | ||
|
25b206ac53 | ||
|
88a4e44fd4 | ||
|
642ea07d6f | ||
|
e85c5ce39d | ||
|
cf753af247 | ||
|
12efe604bb | ||
|
f36f545d75 | ||
|
8fcd544c81 | ||
|
73662ebf83 | ||
|
47a8ec06a1 | ||
|
b611fac20b | ||
|
b11155423c | ||
|
40371cbf2d | ||
|
613590b0d8 | ||
|
4710a65f7a | ||
|
901f65ca05 | ||
|
72cf6806de | ||
|
1b7ae2ed3d |
@@ -1,2 +1,9 @@
|
||||
[cxx]
|
||||
gtest_dep = //lib/gtest:gtest
|
||||
[android]
|
||||
target = Google Inc.:Google APIs:19
|
||||
[ndk]
|
||||
ndk_version = r10e
|
||||
compiler = clang
|
||||
app_platform = android-19
|
||||
cpu_abis = armv7, x86
|
||||
|
17
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Report
|
||||
|
||||
- [ ] I have searched [existing issues](https://github.com/facebook/yoga/issues) and this is not a duplicate
|
||||
|
||||
# Issues and Steps to Reproduce
|
||||
***Replaces this with steps to repro your issue.***
|
||||
|
||||
# Expected Behavior
|
||||
***Describe what you expected would happen.***
|
||||
|
||||
# Actual Behavior
|
||||
***Describe what actually happened.***
|
||||
|
||||
# Link to Code
|
||||
***If you have some code that maintainers can clone/test for themselves, bugs can be resolved much faster. Please paste a link here.***
|
||||
|
||||
***When applicable, use this [fiddle](https://jsfiddle.net/emilsjolander/jckmwztt/) to post a web repro.***
|
55
.gitignore
vendored
@@ -5,6 +5,61 @@
|
||||
/.buckconfig.local
|
||||
/.buckd
|
||||
/gentest/test.html
|
||||
.buckversion
|
||||
|
||||
# Jekyll
|
||||
/.sass-cache/
|
||||
/_site/
|
||||
|
||||
# Visual studio code
|
||||
.vscode
|
||||
*.pdb
|
||||
*.tlog
|
||||
*.obj
|
||||
*.pch
|
||||
*.log
|
||||
*.orig
|
||||
|
||||
# Xcode
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData/
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
|
||||
## Other
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.dSYM.zip
|
||||
*.dSYM
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||
#
|
||||
Pods/
|
||||
|
||||
# Carthage
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||
# Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
||||
|
||||
# Gradle
|
||||
.gradle
|
||||
|
10
.hgignore
@@ -1,10 +0,0 @@
|
||||
.DS_STORE
|
||||
|
||||
/buck-cache/
|
||||
/buck-out/
|
||||
/.buckconfig.local
|
||||
/.buckd
|
||||
/gentest/test.html
|
||||
|
||||
# Visual studio code
|
||||
.vscode
|
1
.swift-version
Normal file
@@ -0,0 +1 @@
|
||||
3.0
|
116
.travis.yml
@@ -6,25 +6,113 @@
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
os: osx
|
||||
osx_image: xcode7.3
|
||||
osx_image: xcode8.2
|
||||
language: cpp
|
||||
compiler: clang
|
||||
|
||||
env:
|
||||
- TARGET=c
|
||||
- TARGET=java
|
||||
- TARGET=net
|
||||
- TARGET=ios
|
||||
- TARGET=js
|
||||
- TARGET=android
|
||||
|
||||
before_install:
|
||||
- brew update
|
||||
- brew update > /dev/null
|
||||
- brew tap facebook/fb
|
||||
- brew install buck
|
||||
- brew cask install java
|
||||
- brew outdated xctool || brew upgrade xctool
|
||||
- brew install mono
|
||||
- export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
|
||||
- export PATH=$JAVA_HOME/bin:$PATH
|
||||
|
||||
# Java
|
||||
- |
|
||||
if [[ $TARGET = "java" ]]; then
|
||||
brew cask install java &&
|
||||
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8) &&
|
||||
export PATH=$JAVA_HOME/bin:$PATH
|
||||
fi
|
||||
|
||||
# .NET
|
||||
- |
|
||||
if [[ $TARGET = "net" ]]; then
|
||||
brew install mono
|
||||
fi
|
||||
|
||||
# iOS
|
||||
- |
|
||||
if [[ $TARGET = "ios" ]]; then
|
||||
brew outdated xctool || brew upgrade xctool
|
||||
fi
|
||||
|
||||
# Emscripten (used for js tests)
|
||||
# Note: cannot be ran on Linux (because it will compile Clang from its sources :|)
|
||||
- |
|
||||
if [[ $TARGET = "js" ]]; then
|
||||
wget -O /tmp/emsdk-portable.tar.gz https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz &&
|
||||
tar xf /tmp/emsdk-portable.tar.gz -C /tmp/ &&
|
||||
/tmp/emsdk_portable/emsdk install latest >& /dev/null &&
|
||||
/tmp/emsdk_portable/emsdk activate latest
|
||||
fi
|
||||
|
||||
# Android
|
||||
- |
|
||||
if [[ $TARGET = "android" ]]; then
|
||||
brew cask install java &&
|
||||
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8) &&
|
||||
export PATH=$JAVA_HOME/bin:$PATH &&
|
||||
brew install android-sdk &&
|
||||
export ANDROID_SDK=/usr/local/opt/android-sdk &&
|
||||
export ANDROID_HOME=/usr/local/opt/android-sdk
|
||||
$ANDROID_SDK/tools/android update sdk --filter android-19,addon-google_apis-google-19
|
||||
fi
|
||||
|
||||
# JavaScript
|
||||
- |
|
||||
if [[ $TARGET = "js" ]]; then (
|
||||
cd javascript &&
|
||||
npm install &&
|
||||
unset CC && unset CXX && unset LINK &&
|
||||
source /tmp/emsdk_portable/emsdk_env.sh &&
|
||||
npm run build:browser
|
||||
) fi
|
||||
|
||||
script:
|
||||
- buck test //:CSSLayout
|
||||
- buck test //java:java
|
||||
- buck test //YogaKit:YogaKit --config cxx.default_platform=iphonesimulator-x86_64 --config cxx.cflags=-DTRAVIS_CI
|
||||
- sh csharp/tests/Facebook.Yoga/test_macos.sh
|
||||
- buck run //benchmark:benchmark
|
||||
- git checkout HEAD^
|
||||
- buck run //benchmark:benchmark
|
||||
# C
|
||||
- |
|
||||
if [[ $TARGET = "c" ]]; then
|
||||
buck test --verbose 0 //:yoga &&
|
||||
buck run --verbose 0 //benchmark:benchmark &&
|
||||
git checkout HEAD^ &&
|
||||
buck run --verbose 0 //benchmark:benchmark
|
||||
fi
|
||||
|
||||
# Java
|
||||
- |
|
||||
if [[ $TARGET = "java" ]]; then
|
||||
buck test --verbose 0 //java:java
|
||||
fi
|
||||
|
||||
# .NET
|
||||
- |
|
||||
if [[ $TARGET = "net" ]]; then
|
||||
sh csharp/tests/Facebook.Yoga/test_macos.sh
|
||||
fi
|
||||
|
||||
# iOS
|
||||
- |
|
||||
if [[ $TARGET = "ios" ]]; then
|
||||
buck test --verbose 0 //YogaKit:YogaKitTests --config cxx.default_platform=iphonesimulator-x86_64
|
||||
fi
|
||||
|
||||
# Android
|
||||
- |
|
||||
if [[ $TARGET = "android" ]]; then
|
||||
buck build --verbose 0 //android/sample:sample
|
||||
fi
|
||||
|
||||
# JavaScript
|
||||
- |
|
||||
if [[ $TARGET = "js" ]]; then (
|
||||
cd javascript &&
|
||||
npm run test:all &&
|
||||
npm run bench
|
||||
) fi
|
||||
|
23
BUCK
@@ -7,14 +7,6 @@
|
||||
|
||||
include_defs('//YOGA_DEFS')
|
||||
|
||||
BASE_COMPILER_FLAGS = [
|
||||
'-fno-omit-frame-pointer',
|
||||
'-fexceptions',
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
'-O3',
|
||||
]
|
||||
|
||||
GMOCK_OVERRIDE_FLAGS = [
|
||||
# gmock does not mark mocked methods as override, ignore the warnings in tests
|
||||
'-Wno-inconsistent-missing-override',
|
||||
@@ -24,25 +16,26 @@ COMPILER_FLAGS = BASE_COMPILER_FLAGS + ['-std=c11', '-fPIC']
|
||||
TEST_COMPILER_FLAGS = BASE_COMPILER_FLAGS + GMOCK_OVERRIDE_FLAGS + ['-std=c++11']
|
||||
|
||||
cxx_library(
|
||||
name = 'CSSLayout',
|
||||
srcs = glob(['CSSLayout/*.c']),
|
||||
tests=[':tests'],
|
||||
exported_headers = subdir_glob([('', 'CSSLayout/*.h')]),
|
||||
name = 'yoga',
|
||||
soname = 'libyogacore.$(ext)',
|
||||
srcs = glob(['yoga/*.c']),
|
||||
tests=[':YogaTests'],
|
||||
exported_headers = subdir_glob([('', 'yoga/*.h')]),
|
||||
header_namespace = '',
|
||||
compiler_flags = COMPILER_FLAGS,
|
||||
deps = [] if THIS_IS_FBOBJC else [
|
||||
csslayout_dep('lib/fb:ndklog'),
|
||||
yoga_dep('lib/fb:ndklog'),
|
||||
],
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
||||
cxx_test(
|
||||
name = 'tests',
|
||||
name = 'YogaTests',
|
||||
contacts = ['emilsj@fb.com'],
|
||||
srcs = glob(['tests/*.cpp']),
|
||||
compiler_flags = TEST_COMPILER_FLAGS,
|
||||
deps = [
|
||||
':CSSLayout',
|
||||
':yoga',
|
||||
GTEST_TARGET,
|
||||
],
|
||||
visibility = ['PUBLIC'],
|
||||
|
@@ -1,10 +1,7 @@
|
||||
# Contributing to css-layout
|
||||
# Contributing to yoga
|
||||
We want to make contributing to this project as easy and transparent as
|
||||
possible.
|
||||
|
||||
## Our Development Process
|
||||
All the development is happening on GitHub first and we have internal tools to sync down to Facebook codebase.
|
||||
|
||||
## Pull Requests
|
||||
We actively welcome your pull requests.
|
||||
1. Fork the repo and create your branch from `master`.
|
||||
@@ -32,5 +29,5 @@ outlined on that page and do not file a public issue.
|
||||
* format.sh
|
||||
|
||||
## License
|
||||
By contributing to css-layout, you agree that your contributions will be licensed
|
||||
By contributing to yoga, you agree that your contributions will be licensed
|
||||
under its BSD license.
|
||||
|
@@ -1,108 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
typedef enum YGFlexDirection {
|
||||
YGFlexDirectionColumn,
|
||||
YGFlexDirectionColumnReverse,
|
||||
YGFlexDirectionRow,
|
||||
YGFlexDirectionRowReverse,
|
||||
YGFlexDirectionCount,
|
||||
} YGFlexDirection;
|
||||
|
||||
typedef enum YGMeasureMode {
|
||||
YGMeasureModeUndefined,
|
||||
YGMeasureModeExactly,
|
||||
YGMeasureModeAtMost,
|
||||
YGMeasureModeCount,
|
||||
} YGMeasureMode;
|
||||
|
||||
typedef enum YGPrintOptions {
|
||||
YGPrintOptionsLayout = 1,
|
||||
YGPrintOptionsStyle = 2,
|
||||
YGPrintOptionsChildren = 4,
|
||||
YGPrintOptionsCount,
|
||||
} YGPrintOptions;
|
||||
|
||||
typedef enum YGEdge {
|
||||
YGEdgeLeft,
|
||||
YGEdgeTop,
|
||||
YGEdgeRight,
|
||||
YGEdgeBottom,
|
||||
YGEdgeStart,
|
||||
YGEdgeEnd,
|
||||
YGEdgeHorizontal,
|
||||
YGEdgeVertical,
|
||||
YGEdgeAll,
|
||||
YGEdgeCount,
|
||||
} YGEdge;
|
||||
|
||||
typedef enum YGPositionType {
|
||||
YGPositionTypeRelative,
|
||||
YGPositionTypeAbsolute,
|
||||
YGPositionTypeCount,
|
||||
} YGPositionType;
|
||||
|
||||
typedef enum YGDimension {
|
||||
YGDimensionWidth,
|
||||
YGDimensionHeight,
|
||||
YGDimensionCount,
|
||||
} YGDimension;
|
||||
|
||||
typedef enum YGJustify {
|
||||
YGJustifyFlexStart,
|
||||
YGJustifyCenter,
|
||||
YGJustifyFlexEnd,
|
||||
YGJustifySpaceBetween,
|
||||
YGJustifySpaceAround,
|
||||
YGJustifyCount,
|
||||
} YGJustify;
|
||||
|
||||
typedef enum YGDirection {
|
||||
YGDirectionInherit,
|
||||
YGDirectionLTR,
|
||||
YGDirectionRTL,
|
||||
YGDirectionCount,
|
||||
} YGDirection;
|
||||
|
||||
typedef enum YGLogLevel {
|
||||
YGLogLevelError,
|
||||
YGLogLevelWarn,
|
||||
YGLogLevelInfo,
|
||||
YGLogLevelDebug,
|
||||
YGLogLevelVerbose,
|
||||
YGLogLevelCount,
|
||||
} YGLogLevel;
|
||||
|
||||
typedef enum YGWrap {
|
||||
YGWrapNoWrap,
|
||||
YGWrapWrap,
|
||||
YGWrapCount,
|
||||
} YGWrap;
|
||||
|
||||
typedef enum YGOverflow {
|
||||
YGOverflowVisible,
|
||||
YGOverflowHidden,
|
||||
YGOverflowScroll,
|
||||
YGOverflowCount,
|
||||
} YGOverflow;
|
||||
|
||||
typedef enum YGExperimentalFeature {
|
||||
YGExperimentalFeatureRounding,
|
||||
YGExperimentalFeatureWebFlexBasis,
|
||||
YGExperimentalFeatureCount,
|
||||
} YGExperimentalFeature;
|
||||
|
||||
typedef enum YGAlign {
|
||||
YGAlignAuto,
|
||||
YGAlignFlexStart,
|
||||
YGAlignCenter,
|
||||
YGAlignFlexEnd,
|
||||
YGAlignStretch,
|
||||
YGAlignCount,
|
||||
} YGAlign;
|
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
BSD License
|
||||
|
||||
For css-layout software
|
||||
For yoga software
|
||||
|
||||
Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
|
||||
|
9
LICENSE-examples
Normal file
@@ -0,0 +1,9 @@
|
||||
The examples provided by Facebook are for non-commercial testing and evaluation
|
||||
purposes only. Facebook reserves all rights not expressly granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
2
PATENTS
@@ -1,6 +1,6 @@
|
||||
Additional Grant of Patent Rights Version 2
|
||||
|
||||
"Software" means the CSS Layout software distributed by Facebook, Inc.
|
||||
"Software" means the yoga software distributed by Facebook, Inc.
|
||||
|
||||
Facebook, Inc. (“Facebook”) hereby grants to each recipient of the Software
|
||||
(“you”) a perpetual, worldwide, royalty-free, non-exclusive, irrevocable
|
||||
|
169
README.md
@@ -1,162 +1,37 @@
|
||||
# CSSLayout [](https://travis-ci.org/facebook/css-layout)
|
||||
# Yoga [](http://cocoapods.org/pods/YogaKit) [](https://www.npmjs.com/package/yoga-layout)
|
||||
|
||||
## NOTICE
|
||||
A lot is changing this week in the API regarding naming. We suggest you hold off updating to the latest version of the code until this notice is gone. Expect it to take about a week.
|
||||
[](https://travis-ci.org/facebook/yoga)
|
||||
[](https://travis-ci.org/facebook/yoga)
|
||||
[](https://travis-ci.org/facebook/yoga)
|
||||
[](https://travis-ci.org/facebook/yoga)
|
||||
[](https://travis-ci.org/facebook/yoga)
|
||||
[](https://travis-ci.org/facebook/yoga)
|
||||
|
||||
## Goals
|
||||
CSSLayout is a cross-platform implementation of flexbox. The goal of CSSLayout is allow native developers to have the same expressive layout system as developers developing for the modern web are used to. CSSLayout allows developers for web, android, iOS, and windows to use the same layout primitives across platforms. This saves time, increases collaboration between platform teams, and makes it easier for developers to work on multiple platforms.
|
||||
## Building
|
||||
Yoga builds with [buck](https://buckbuild.com). Make sure you install buck before contributing to Yoga. Yoga's main implementation is in C, with bindings to supported languages and frameworks. When making changes to Yoga please ensure the changes are also propagated to these bindings when applicable.
|
||||
|
||||
The goal of CSSLayout is not to re-implement all of css. CSSLayout only targets flexbox, and does not have any plans on implementing support for tables, floats, or any other css concepts. CSSLayout also does not plan on supporting styling properties which do not affect layout such as color or background properties.
|
||||
## Testing
|
||||
For testing we rely on [gtest](https://github.com/google/googletest) as a submodule. After cloning Yoga run `git submodule init` followed by `git submodule update`.
|
||||
|
||||
For any changes you make you should ensure that all the tests are passing. In case you make any fixes or additions to the library please also add tests for that change to ensure we don't break anything in the future. Tests are located in the `tests` directory. Run the tests by executing `buck test //:yoga`.
|
||||
|
||||
## Differences from web
|
||||
CSSLayout tries to stay as close as possible to the web implementation of flexbox. There are however certain cases where CSSLayout differs from the web implementation.
|
||||
|
||||
### Default values
|
||||
CSSLayout has chosen to make changes to the default values of certain properties. These default values were chosen based on our usage of the library. When testing layout with tools such as JSFiddle you can apply the following css style to ensure the defaults match those of CSSLayout. Or fork the [following JSFiddle](http://jsfiddle.net/vjeux/y11txxv9/).
|
||||
|
||||
```css
|
||||
div, span {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
flex-shrink: 0;
|
||||
align-content: flex-start;
|
||||
|
||||
border: 0 solid black;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
```
|
||||
|
||||
- `box-sizing: border-box` is the most convenient way to express the relation between `width` and `borderWidth`.
|
||||
- Everything is `display: flex` by default. All the behaviors of `block` and `inline-block` can be expressed in term of `flex` but not the opposite.
|
||||
- All the flex elements are oriented from top to bottom, left to right and do not shrink. This is how things are laid out using the default CSS settings and what you'd expect.
|
||||
- Everything is `position: relative`. This makes `position: absolute` target the direct parent and not some parent which is either `relative` or `absolute`. If you want to position an element relative to something else, you should move it in the DOM instead of relying of CSS. It also makes `top, left, right, bottom` do something when not specifying `position: absolute`.
|
||||
|
||||
### Size units
|
||||
CSSLayout currently only supports pixel sizes. The reason being that we have not seen the need for any other units. We would like to support percentage units sometime in the future.
|
||||
|
||||
### -start and -end properties
|
||||
We think supporting RTL locales is very important. Therefor CSSLayout supports non-standards -start and -end suffixed versions of margin, padding, border, and position.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
### C
|
||||
The full API can be found in `CSSLayout/CSSLayout.h`.
|
||||
|
||||
```c
|
||||
CSSNodeRef root = CSSNodeNew();
|
||||
CSSNodeStyleSetWidth(root, 100);
|
||||
CSSNodeStyleSetHeight(root, 100);
|
||||
|
||||
for (uint32_t i = 0; i < 10; i++) {
|
||||
CSSNodeRef child = CSSNodeNew();
|
||||
CSSNodeStyleSetHeight(child, 10);
|
||||
CSSNodeInsertChild(root, child, 0);
|
||||
}
|
||||
|
||||
CSSNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||
|
||||
// Get for resulting layout
|
||||
CSSNodeLayoutGetLeft(root);
|
||||
CSSNodeLayoutGetTop(root);
|
||||
CSSNodeLayoutGetWidth(root);
|
||||
CSSNodeLayoutGetHeight(root);
|
||||
```
|
||||
|
||||
### Java
|
||||
The full API can be found in `java/com/facebook/csslayout/CSSNode.java`.
|
||||
|
||||
```java
|
||||
CSSNode root = new CSSNode();
|
||||
root.setStyleWidth(100);
|
||||
root.setStyleHeight(100);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
CSSNode child = new CSSNode();
|
||||
child.setStyleHeight(10);
|
||||
root.addChildAt(child, 0);
|
||||
}
|
||||
|
||||
root.calculateLayout(new CSSLayoutContext());
|
||||
|
||||
// Get for resulting layout
|
||||
root.getLayoutX();
|
||||
root.getLayoutY();
|
||||
root.getLayoutWidth();
|
||||
root.getLayoutHeight();
|
||||
```
|
||||
|
||||
### UIKit
|
||||
The full API can be found in `YogaKit/UIView+Yoga.h`.
|
||||
|
||||
```objective-c
|
||||
UIView *root = [UIView new];
|
||||
[root yg_setUsesYoga:YES];
|
||||
[root yg_setWidth:100];
|
||||
[root yg_setHeight:100];
|
||||
|
||||
for (NSUInteger i = 0; i < 10; i++) {
|
||||
UIView *child = [UIView new];
|
||||
[child yg_setUsesYoga:YES];
|
||||
[child yg_setHeight:10];
|
||||
[root addSubview:child];
|
||||
}
|
||||
|
||||
// Resulting layout will be set on the UIView hierarchy frames.
|
||||
[root yg_applyLayout];
|
||||
```
|
||||
|
||||
### .NET
|
||||
The full API can be found in `csharp/Facebook.CSSLayout/CSSNode.cs`.
|
||||
|
||||
```csharp
|
||||
var root = new CSSNode();
|
||||
root.StyleWidth = 100;
|
||||
root.StyleHeight = 100;
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var child = new CSSNode();
|
||||
child.StyleHeight = 10;
|
||||
root.Insert(0, child);
|
||||
}
|
||||
|
||||
// Get for resulting layout
|
||||
root.LayoutX;
|
||||
root.LayoutY;
|
||||
root.LayoutWidth;
|
||||
root.LayoutHeight;
|
||||
```
|
||||
|
||||
## Contributing
|
||||
To contribute to CSSLayout you need to first install [buck](https://buckbuild.com) which is the build system used by CSSLayout. CSSLayout is implemented in C with language bindings for Java, Objective-C, and .NET. When making changes to `CSSLayout/CSSLayout.h` please ensure to update `java/jni/CSSJNI.h`, `java/com/facebook/csslayout/CSSNode.java`, `uikit/CSSLayout/UIView+CSSLayout.m`, and `csharp/Facebook.CSSLayout/CSSNode.cs` to reflect the API change. Before submitting any code please run `format.sh` to ensure the code matches the project's code style.
|
||||
|
||||
Before making any larger changes to CSSLayout please open an issue with a RFC so the changes can be discussed first. Generally we are very open to changes and improvements that will benefit the community.
|
||||
|
||||
### Testing
|
||||
For any changes you make you should ensure that all the tests are passing. In case you make any fixes or additions to the library please also add at least one test to ensure we don't break anything in the future. Tests are located in `tests/CSSLayoutTest.cpp`. Run the tests by executing `buck test //:CSSLayout`.
|
||||
|
||||
Instead of manually writing a test which ensures parity with web implementations of flexbox you can run `gentest/gentest.rb` to generated a test for you. You can write html which you want to verify in CSSLayout, in `gentest/fixtures` folder, such as the following.
|
||||
Instead of manually writing a test which ensures parity with web implementations of Flexbox you can run `gentest/gentest.rb` to generated a test for you. You can write html which you want to verify in Yoga, in `gentest/fixtures` folder, such as the following.
|
||||
|
||||
```html
|
||||
<div style="width: 100px; height: 100px; align-items: center;">
|
||||
<div id="my_test" style="width: 100px; height: 100px; align-items: center;">
|
||||
<div style="width: 50px; height: 50px;"></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
Run `gentest/gentest.rb` to generate test code and re-run `buck test //:CSSLayout` to validate the behavior. One test case will be generated for every root `div` in the input html.
|
||||
Run `gentest/gentest.rb` to generate test code and re-run `buck test //:yoga` to validate the behavior. One test case will be generated for every root `div` in the input html.
|
||||
|
||||
You may need to install the latest watir-webdriver gem (`gem install watir-webdriver`) and [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/) to run `gentest/gentest.rb` Ruby script.
|
||||
|
||||
#### .NET
|
||||
.NET testing is not integrated in buck yet, you might need to set up .NET testing environment. We have a script which to launch C# test on macOS, `csharp/tests/Facebook.CSSLayout/test_macos.sh`.
|
||||
### .NET
|
||||
.NET testing is not integrated in buck yet, you might need to set up .NET testing environment. We have a script which to launch C# test on macOS, `csharp/tests/Facebook.Yoga/test_macos.sh`.
|
||||
|
||||
### Benchmarks
|
||||
Benchmarks are located in `benchmarks/CSSBenchmark.c` and can be run with `buck run //benchmarks:benchmarks`. If you think your change has affected performance please run this before and after your change to validate that nothing has regressed.
|
||||
## Code style
|
||||
For the main C implementation of Yoga clang-format is used to ensure a consistent code style. Please run `bash format.sh` before submitting a pull request. For other languages just try to follow the current code style.
|
||||
|
||||
## Benchmarks
|
||||
Benchmarks are located in `benchmark/YGBenchmark.c` and can be run with `buck run //benchmark:benchmark`. If you think your change has affected performance please run this before and after your change to validate that nothing has regressed. Benchmarks are run on every commit in CI.
|
||||
|
31
YOGA_DEFS
@@ -1,5 +1,6 @@
|
||||
|
||||
CSSLAYOUT_ROOT = '//...'
|
||||
YOGA_ROOT = '//...'
|
||||
JAVA_TARGET = '//java:java'
|
||||
INFER_ANNOTATIONS_TARGET = '//lib/infer-annotations:infer-annotations'
|
||||
JSR_305_TARGET = '//lib/jsr-305:jsr-305'
|
||||
JUNIT_TARGET = '//lib/junit:junit'
|
||||
@@ -8,20 +9,34 @@ SOLOADER_TARGET = '//lib/soloader:soloader'
|
||||
GTEST_TARGET = '//lib/gtest:gtest'
|
||||
JNI_TARGET = '//lib/jni:jni'
|
||||
FBJNI_TARGET = '//lib/fb:fbjni'
|
||||
APPCOMPAT_TARGET = '//lib/appcompat:appcompat'
|
||||
ANDROID_SUPPORT_TARGET = '//lib/android-support:android-support'
|
||||
ANDROID_TARGET = '//android:android'
|
||||
ANDROID_JAVA_TARGET = '//android/src/main/java/com/facebook/yoga/android:android'
|
||||
ANDROID_RES_TARGET = '//android:res'
|
||||
ANDROID_SAMPLE_JAVA_TARGET = '//android/sample/java/com/facebook/samples/yoga:yoga'
|
||||
ANDROID_SAMPLE_RES_TARGET = '//android/sample:res'
|
||||
|
||||
THIS_IS_FBOBJC = False
|
||||
|
||||
CXX_LIBRARY_WHITELIST = [
|
||||
'//:CSSLayout',
|
||||
'//:yoga',
|
||||
'//lib/fb:fbjni',
|
||||
'//java:jni',
|
||||
]
|
||||
|
||||
def csslayout_dep(dep):
|
||||
BASE_COMPILER_FLAGS = [
|
||||
'-fno-omit-frame-pointer',
|
||||
'-fexceptions',
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
'-O3',
|
||||
]
|
||||
|
||||
def yoga_dep(dep):
|
||||
return '//' + dep
|
||||
|
||||
class allow_unsafe_import:
|
||||
def __enter__(self):
|
||||
pass
|
||||
def __exit__(self, type, value, traceback):
|
||||
pass
|
||||
with allow_unsafe_import():
|
||||
import os.path
|
||||
def isdir(filename):
|
||||
return os.path.isdir(filename)
|
||||
|
28
Yoga.podspec
Normal file
@@ -0,0 +1,28 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = 'Yoga'
|
||||
spec.version = '1.1.0'
|
||||
spec.license = { :type => 'BSD', :file => "LICENSE" }
|
||||
spec.homepage = 'https://facebook.github.io/yoga/'
|
||||
spec.documentation_url = 'https://facebook.github.io/yoga/docs/api/c/'
|
||||
|
||||
spec.summary = 'Yoga is a cross-platform layout engine which implements Flexbox.'
|
||||
spec.description = 'Yoga is a cross-platform layout engine enabling maximum collaboration within your team by implementing an API many designers are familiar with, and opening it up to developers across different platforms.'
|
||||
|
||||
spec.authors = 'Facebook'
|
||||
spec.source = {
|
||||
:git => 'https://github.com/facebook/yoga.git',
|
||||
:tag => 'v2017.02.07.00',
|
||||
}
|
||||
|
||||
spec.module_name = 'yoga'
|
||||
spec.requires_arc = false
|
||||
spec.compiler_flags = [
|
||||
'-fno-omit-frame-pointer',
|
||||
'-fexceptions',
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
'-std=c11',
|
||||
'-fPIC'
|
||||
]
|
||||
spec.source_files = 'yoga/**/*.{c,h}'
|
||||
end
|
29
YogaKit.podspec
Normal file
@@ -0,0 +1,29 @@
|
||||
podspec = Pod::Spec.new do |spec|
|
||||
spec.name = 'YogaKit'
|
||||
spec.version = '1.1.0'
|
||||
spec.license = { :type => 'BSD', :file => "LICENSE" }
|
||||
spec.homepage = 'https://facebook.github.io/yoga/'
|
||||
spec.documentation_url = 'https://facebook.github.io/yoga/docs/api/yogakit/'
|
||||
|
||||
spec.summary = 'Yoga is a cross-platform layout engine which implements Flexbox.'
|
||||
spec.description = 'Yoga is a cross-platform layout engine enabling maximum collaboration within your team by implementing an API many designers are familiar with, and opening it up to developers across different platforms.'
|
||||
|
||||
spec.authors = 'Facebook'
|
||||
spec.source = {
|
||||
:git => 'https://github.com/facebook/yoga.git',
|
||||
:tag => 'v2017.02.07.00',
|
||||
}
|
||||
|
||||
spec.platform = :ios
|
||||
spec.ios.deployment_target = '8.0'
|
||||
spec.ios.frameworks = 'UIKit'
|
||||
|
||||
spec.dependency 'Yoga', '~> 1.1'
|
||||
spec.source_files = 'YogaKit/Source/*.{h,m}'
|
||||
spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h'
|
||||
spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h'
|
||||
end
|
||||
|
||||
# See https://github.com/facebook/yoga/pull/366
|
||||
podspec.attributes_hash["readme"] = "YogaKit/README.md"
|
||||
podspec
|
1
YogaKit/.swift-version
Normal file
@@ -0,0 +1 @@
|
||||
3.0.2
|
13
YogaKit/BUCK
@@ -7,7 +7,7 @@
|
||||
|
||||
include_defs('//YOGA_DEFS')
|
||||
|
||||
UIKIT_CSSLAYOUT_COMPILER_FLAGS = [
|
||||
COMPILER_FLAGS = [
|
||||
'-fobjc-arc',
|
||||
'-Wconditional-uninitialized',
|
||||
'-Wdangling-else',
|
||||
@@ -29,23 +29,22 @@ UIKIT_CSSLAYOUT_COMPILER_FLAGS = [
|
||||
|
||||
apple_library(
|
||||
name = 'YogaKit',
|
||||
compiler_flags = UIKIT_CSSLAYOUT_COMPILER_FLAGS,
|
||||
tests = [':YogaKitTests'],
|
||||
srcs = glob(['*.m']),
|
||||
exported_headers = glob(['*.h']),
|
||||
compiler_flags = COMPILER_FLAGS,
|
||||
srcs = glob(['Source/**/*.m']),
|
||||
exported_headers = glob(['Source/**/*.h']),
|
||||
frameworks = [
|
||||
'$SDKROOT/System/Library/Frameworks/Foundation.framework',
|
||||
'$SDKROOT/System/Library/Frameworks/UIKit.framework',
|
||||
],
|
||||
deps = [
|
||||
csslayout_dep(':CSSLayout'),
|
||||
yoga_dep(':yoga'),
|
||||
],
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
||||
apple_test(
|
||||
name = 'YogaKitTests',
|
||||
compiler_flags = UIKIT_CSSLAYOUT_COMPILER_FLAGS,
|
||||
compiler_flags = COMPILER_FLAGS,
|
||||
info_plist = 'Tests/Info.plist',
|
||||
srcs = glob(['Tests/**/*.m']),
|
||||
frameworks = [
|
||||
|
46
YogaKit/CHANGELOG.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# CHANGELOG
|
||||
|
||||
The changelog for `YogaKit`.
|
||||
|
||||
1.2.0 (**upcoming release**)
|
||||
-----
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- `applyLayout()` has now been changed to `applyLayout(preservingOrigin:)`.
|
||||
|
||||
- Computed properties are no longer reflected in getter's of the affected properties.
|
||||
```swift
|
||||
// OLD
|
||||
view.yoga.margin = 10
|
||||
view.yoga.marginTop // 10
|
||||
view.yoga.marginLeft // 10
|
||||
|
||||
// NEW
|
||||
view.yoga.margin = 10
|
||||
view.yoga.marginTop // 0
|
||||
view.yoga.marginLeft // 0
|
||||
```
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Pixel Rounding now uses `roundf()` instead of `round()`.
|
||||
|
||||
- There is now a method that allows "bulk" updates to YGLayout.
|
||||
```objc
|
||||
[view configureLayoutWithBlock:^(YGLayout *layout) {
|
||||
layout.isEnabled = YES;
|
||||
layout.width = 50;
|
||||
layout.height = 50;
|
||||
}];
|
||||
```
|
||||
|
||||
```swift
|
||||
view.configureLayout { (layout) in
|
||||
layout.isEnabled = true
|
||||
layout.width = 50
|
||||
layout.height = 50
|
||||
}
|
||||
```
|
||||
|
||||
- Added new `isDirty` property, and make `markDirty` a little more performant.
|
22
YogaKit/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# YogaKit
|
||||
|
||||
[](https://cocoapods.org/pods/YogaKit)
|
||||
[](https://facebook.github.io/yoga/docs/api/yogakit/)
|
||||
[](https://facebook.github.io/yoga/docs/api/yogakit/)
|
||||
|
||||
## Installation
|
||||
YogaKit is available to install via [CocoaPods](https://cocoapods.org/).
|
||||
|
||||
```
|
||||
pod 'YogaKit', '~> 1.1'
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
Checkout the docs [here](https://facebook.github.io/yoga/docs/api/yogakit/).
|
||||
|
||||
We also have a sample project. To try it out, clone this repo and open `YogaKitSample.xcodeproj` in the [YogaKitSample](https://github.com/facebook/yoga/tree/master/YogaKit/YogaKitSample) directory.
|
||||
|
||||
## Contributing
|
||||
We welcome all pull-requests! At Facebook we sync the open source version of `YogaKit` daily, so we're always testing the latest changes.
|
||||
|
||||
See the [CONTRIBUTING](https://github.com/facebook/yoga/blob/master/CONTRIBUTING) file for how to help out.
|
34
YogaKit/Source/UIView+Yoga.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "YGLayout.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void (^YGLayoutConfigurationBlock)(YGLayout *);
|
||||
|
||||
@interface UIView (Yoga)
|
||||
|
||||
/**
|
||||
The YGLayout that is attached to this view. It is lazily created.
|
||||
*/
|
||||
@property (nonatomic, readonly, strong) YGLayout *yoga;
|
||||
|
||||
/**
|
||||
In ObjC land, every time you access `view.yoga.*` you are adding another `objc_msgSend`
|
||||
to your code. If you plan on making multiple changes to YGLayout, it's more performant
|
||||
to use this method, which uses a single objc_msgSend call.
|
||||
*/
|
||||
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block
|
||||
NS_SWIFT_NAME(configureLayout(block:));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
36
YogaKit/Source/UIView+Yoga.m
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "UIView+Yoga.h"
|
||||
#import "YGLayout+Private.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
static const void *kYGYogaAssociatedKey = &kYGYogaAssociatedKey;
|
||||
|
||||
@implementation UIView (YogaKit)
|
||||
|
||||
- (YGLayout *)yoga
|
||||
{
|
||||
YGLayout *yoga = objc_getAssociatedObject(self, kYGYogaAssociatedKey);
|
||||
if (!yoga) {
|
||||
yoga = [[YGLayout alloc] initWithView:self];
|
||||
objc_setAssociatedObject(self, kYGYogaAssociatedKey, yoga, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
return yoga;
|
||||
}
|
||||
|
||||
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block
|
||||
{
|
||||
if (block != nil) {
|
||||
block(self.yoga);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
19
YogaKit/Source/YGLayout+Private.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "YGLayout.h"
|
||||
#import <yoga/Yoga.h>
|
||||
|
||||
@interface YGLayout ()
|
||||
|
||||
@property (nonatomic, assign, readonly) YGNodeRef node;
|
||||
|
||||
- (instancetype)initWithView:(UIView *)view;
|
||||
|
||||
@end
|
126
YogaKit/Source/YGLayout.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <yoga/YGEnums.h>
|
||||
|
||||
@interface YGLayout : NSObject
|
||||
|
||||
/**
|
||||
The property that decides if we should include this view when calculating layout. Defaults to YES.
|
||||
*/
|
||||
@property (nonatomic, readwrite, assign, setter=setIncludedInLayout:) BOOL isIncludedInLayout;
|
||||
|
||||
/**
|
||||
The property that decides during layout/sizing whether or not styling properties should be applied.
|
||||
Defaults to NO.
|
||||
*/
|
||||
@property (nonatomic, readwrite, assign, setter=setEnabled:) BOOL isEnabled;
|
||||
|
||||
@property (nonatomic, readwrite, assign) YGDirection direction;
|
||||
@property (nonatomic, readwrite, assign) YGFlexDirection flexDirection;
|
||||
@property (nonatomic, readwrite, assign) YGJustify justifyContent;
|
||||
@property (nonatomic, readwrite, assign) YGAlign alignContent;
|
||||
@property (nonatomic, readwrite, assign) YGAlign alignItems;
|
||||
@property (nonatomic, readwrite, assign) YGAlign alignSelf;
|
||||
@property (nonatomic, readwrite, assign) YGPositionType position;
|
||||
@property (nonatomic, readwrite, assign) YGWrap flexWrap;
|
||||
@property (nonatomic, readwrite, assign) YGOverflow overflow;
|
||||
@property (nonatomic, readwrite, assign) YGDisplay display;
|
||||
|
||||
@property (nonatomic, readwrite, assign) CGFloat flexGrow;
|
||||
@property (nonatomic, readwrite, assign) CGFloat flexShrink;
|
||||
@property (nonatomic, readwrite, assign) CGFloat flexBasis;
|
||||
|
||||
@property (nonatomic, readwrite, assign) CGFloat left;
|
||||
@property (nonatomic, readwrite, assign) CGFloat top;
|
||||
@property (nonatomic, readwrite, assign) CGFloat right;
|
||||
@property (nonatomic, readwrite, assign) CGFloat bottom;
|
||||
@property (nonatomic, readwrite, assign) CGFloat start;
|
||||
@property (nonatomic, readwrite, assign) CGFloat end;
|
||||
|
||||
@property (nonatomic, readwrite, assign) CGFloat marginLeft;
|
||||
@property (nonatomic, readwrite, assign) CGFloat marginTop;
|
||||
@property (nonatomic, readwrite, assign) CGFloat marginRight;
|
||||
@property (nonatomic, readwrite, assign) CGFloat marginBottom;
|
||||
@property (nonatomic, readwrite, assign) CGFloat marginStart;
|
||||
@property (nonatomic, readwrite, assign) CGFloat marginEnd;
|
||||
@property (nonatomic, readwrite, assign) CGFloat marginHorizontal;
|
||||
@property (nonatomic, readwrite, assign) CGFloat marginVertical;
|
||||
@property (nonatomic, readwrite, assign) CGFloat margin;
|
||||
|
||||
@property (nonatomic, readwrite, assign) CGFloat paddingLeft;
|
||||
@property (nonatomic, readwrite, assign) CGFloat paddingTop;
|
||||
@property (nonatomic, readwrite, assign) CGFloat paddingRight;
|
||||
@property (nonatomic, readwrite, assign) CGFloat paddingBottom;
|
||||
@property (nonatomic, readwrite, assign) CGFloat paddingStart;
|
||||
@property (nonatomic, readwrite, assign) CGFloat paddingEnd;
|
||||
@property (nonatomic, readwrite, assign) CGFloat paddingHorizontal;
|
||||
@property (nonatomic, readwrite, assign) CGFloat paddingVertical;
|
||||
@property (nonatomic, readwrite, assign) CGFloat padding;
|
||||
|
||||
@property (nonatomic, readwrite, assign) CGFloat borderLeftWidth;
|
||||
@property (nonatomic, readwrite, assign) CGFloat borderTopWidth;
|
||||
@property (nonatomic, readwrite, assign) CGFloat borderRightWidth;
|
||||
@property (nonatomic, readwrite, assign) CGFloat borderBottomWidth;
|
||||
@property (nonatomic, readwrite, assign) CGFloat borderStartWidth;
|
||||
@property (nonatomic, readwrite, assign) CGFloat borderEndWidth;
|
||||
@property (nonatomic, readwrite, assign) CGFloat borderWidth;
|
||||
|
||||
@property (nonatomic, readwrite, assign) CGFloat width;
|
||||
@property (nonatomic, readwrite, assign) CGFloat height;
|
||||
@property (nonatomic, readwrite, assign) CGFloat minWidth;
|
||||
@property (nonatomic, readwrite, assign) CGFloat minHeight;
|
||||
@property (nonatomic, readwrite, assign) CGFloat maxWidth;
|
||||
@property (nonatomic, readwrite, assign) CGFloat maxHeight;
|
||||
|
||||
// Yoga specific properties, not compatible with flexbox specification
|
||||
@property (nonatomic, readwrite, assign) CGFloat aspectRatio;
|
||||
|
||||
/**
|
||||
Get the resolved direction of this node. This won't be YGDirectionInherit
|
||||
*/
|
||||
@property (nonatomic, readonly, assign) YGDirection resolvedDirection;
|
||||
|
||||
/**
|
||||
Perform a layout calculation and update the frames of the views in the 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
|
||||
NS_SWIFT_NAME(applyLayout(preservingOrigin:));
|
||||
|
||||
/**
|
||||
Returns the size of the view if no constraints were given. This could equivalent to calling [self
|
||||
sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||
*/
|
||||
@property (nonatomic, readonly, assign) CGSize intrinsicSize;
|
||||
|
||||
/**
|
||||
Returns the number of children that are using Flexbox.
|
||||
*/
|
||||
@property (nonatomic, readonly, assign) NSUInteger numberOfChildren;
|
||||
|
||||
/**
|
||||
Return a BOOL indiciating whether or not we this node contains any subviews that are included in
|
||||
Yoga's layout.
|
||||
*/
|
||||
@property (nonatomic, readonly, assign) BOOL isLeaf;
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
@property (nonatomic, readonly, assign) BOOL isDirty;
|
||||
|
||||
/**
|
||||
Mark that a view's layout needs to be recalculated. Only works for leaf views.
|
||||
*/
|
||||
- (void)markDirty;
|
||||
|
||||
@end
|
414
YogaKit/Source/YGLayout.m
Normal file
@@ -0,0 +1,414 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "YGLayout+Private.h"
|
||||
#import "UIView+Yoga.h"
|
||||
|
||||
#define YG_PROPERTY(type, lowercased_name, capitalized_name) \
|
||||
- (type)lowercased_name \
|
||||
{ \
|
||||
return YGNodeStyleGet##capitalized_name(self.node); \
|
||||
} \
|
||||
\
|
||||
- (void)set##capitalized_name:(type)lowercased_name \
|
||||
{ \
|
||||
YGNodeStyleSet##capitalized_name(self.node, lowercased_name); \
|
||||
}
|
||||
|
||||
#define YG_VALUE_PROPERTY(lowercased_name, capitalized_name) \
|
||||
- (CGFloat)lowercased_name \
|
||||
{ \
|
||||
YGValue value = YGNodeStyleGet##capitalized_name(self.node); \
|
||||
if (value.unit == YGUnitPoint) { \
|
||||
return value.value; \
|
||||
} else { \
|
||||
return YGUndefined; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
- (void)set##capitalized_name:(CGFloat)lowercased_name \
|
||||
{ \
|
||||
YGNodeStyleSet##capitalized_name(self.node, lowercased_name); \
|
||||
}
|
||||
|
||||
#define YG_EDGE_PROPERTY_GETTER(lowercased_name, capitalized_name, property, edge) \
|
||||
- (CGFloat)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(lowercased_name, capitalized_name, property, edge) \
|
||||
YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
|
||||
|
||||
#define YG_VALUE_EDGE_PROPERTY_GETTER(objc_lowercased_name, objc_capitalized_name, c_name, edge) \
|
||||
- (CGFloat)objc_lowercased_name \
|
||||
{ \
|
||||
YGValue value = YGNodeStyleGet##c_name(self.node, edge); \
|
||||
if (value.unit == YGUnitPoint) { \
|
||||
return value.value; \
|
||||
} else { \
|
||||
return YGUndefined; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define YG_VALUE_EDGE_PROPERTY_SETTER(objc_lowercased_name, objc_capitalized_name, c_name, edge) \
|
||||
- (void)set##objc_capitalized_name:(CGFloat)objc_lowercased_name \
|
||||
{ \
|
||||
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name); \
|
||||
}
|
||||
|
||||
#define YG_VALUE_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
|
||||
YG_VALUE_EDGE_PROPERTY_GETTER(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)
|
||||
|
||||
@interface YGLayout ()
|
||||
|
||||
@property (nonatomic, weak, readonly) UIView *view;
|
||||
|
||||
@end
|
||||
|
||||
@implementation YGLayout
|
||||
|
||||
@synthesize isEnabled=_isEnabled;
|
||||
@synthesize isIncludedInLayout=_isIncludedInLayout;
|
||||
@synthesize node=_node;
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
YGSetExperimentalFeatureEnabled(YGExperimentalFeatureWebFlexBasis, true);
|
||||
}
|
||||
|
||||
- (instancetype)initWithView:(UIView*)view
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_view = view;
|
||||
_node = YGNodeNew();
|
||||
YGNodeSetContext(_node, (__bridge void *) view);
|
||||
_isEnabled = NO;
|
||||
_isIncludedInLayout = YES;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
YGNodeFree(self.node);
|
||||
}
|
||||
|
||||
- (BOOL)isDirty
|
||||
{
|
||||
return YGNodeIsDirty(self.node);
|
||||
}
|
||||
|
||||
- (void)markDirty
|
||||
{
|
||||
if (self.isDirty || !self.isLeaf) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Yoga is not happy if we try to mark a node as "dirty" before we have set
|
||||
// the measure function. Since we already know that this is a leaf,
|
||||
// this *should* be fine. Forgive me Hack Gods.
|
||||
const YGNodeRef node = self.node;
|
||||
if (YGNodeGetMeasureFunc(node) == NULL) {
|
||||
YGNodeSetMeasureFunc(node, YGMeasureView);
|
||||
}
|
||||
|
||||
YGNodeMarkDirty(node);
|
||||
}
|
||||
|
||||
- (NSUInteger)numberOfChildren
|
||||
{
|
||||
return YGNodeGetChildCount(self.node);
|
||||
}
|
||||
|
||||
- (BOOL)isLeaf
|
||||
{
|
||||
NSAssert([NSThread isMainThread], @"This method must be called on the main thread.");
|
||||
if (self.isEnabled) {
|
||||
for (UIView *subview in self.view.subviews) {
|
||||
YGLayout *const yoga = subview.yoga;
|
||||
if (yoga.isEnabled && yoga.isIncludedInLayout) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Style
|
||||
|
||||
- (YGPositionType)position
|
||||
{
|
||||
return YGNodeStyleGetPositionType(self.node);
|
||||
}
|
||||
|
||||
- (void)setPosition:(YGPositionType)position
|
||||
{
|
||||
YGNodeStyleSetPositionType(self.node, position);
|
||||
}
|
||||
|
||||
YG_PROPERTY(YGDirection, direction, Direction)
|
||||
YG_PROPERTY(YGFlexDirection, flexDirection, FlexDirection)
|
||||
YG_PROPERTY(YGJustify, justifyContent, JustifyContent)
|
||||
YG_PROPERTY(YGAlign, alignContent, AlignContent)
|
||||
YG_PROPERTY(YGAlign, alignItems, AlignItems)
|
||||
YG_PROPERTY(YGAlign, alignSelf, AlignSelf)
|
||||
YG_PROPERTY(YGWrap, flexWrap, FlexWrap)
|
||||
YG_PROPERTY(YGOverflow, overflow, Overflow)
|
||||
YG_PROPERTY(YGDisplay, display, Display)
|
||||
|
||||
YG_PROPERTY(CGFloat, flexGrow, FlexGrow)
|
||||
YG_PROPERTY(CGFloat, flexShrink, FlexShrink)
|
||||
YG_VALUE_PROPERTY(flexBasis, FlexBasis)
|
||||
|
||||
YG_VALUE_EDGE_PROPERTY(left, Left, Position, YGEdgeLeft)
|
||||
YG_VALUE_EDGE_PROPERTY(top, Top, Position, YGEdgeTop)
|
||||
YG_VALUE_EDGE_PROPERTY(right, Right, Position, YGEdgeRight)
|
||||
YG_VALUE_EDGE_PROPERTY(bottom, Bottom, Position, YGEdgeBottom)
|
||||
YG_VALUE_EDGE_PROPERTY(start, Start, Position, YGEdgeStart)
|
||||
YG_VALUE_EDGE_PROPERTY(end, End, Position, YGEdgeEnd)
|
||||
YG_VALUE_EDGES_PROPERTIES(margin, Margin)
|
||||
YG_VALUE_EDGES_PROPERTIES(padding, Padding)
|
||||
|
||||
YG_EDGE_PROPERTY(borderLeftWidth, BorderLeftWidth, Border, YGEdgeLeft)
|
||||
YG_EDGE_PROPERTY(borderTopWidth, BorderTopWidth, Border, YGEdgeTop)
|
||||
YG_EDGE_PROPERTY(borderRightWidth, BorderRightWidth, Border, YGEdgeRight)
|
||||
YG_EDGE_PROPERTY(borderBottomWidth, BorderBottomWidth, Border, YGEdgeBottom)
|
||||
YG_EDGE_PROPERTY(borderStartWidth, BorderStartWidth, Border, YGEdgeStart)
|
||||
YG_EDGE_PROPERTY(borderEndWidth, BorderEndWidth, Border, YGEdgeEnd)
|
||||
YG_EDGE_PROPERTY(borderWidth, BorderWidth, Border, YGEdgeAll)
|
||||
|
||||
YG_VALUE_PROPERTY(width, Width)
|
||||
YG_VALUE_PROPERTY(height, Height)
|
||||
YG_VALUE_PROPERTY(minWidth, MinWidth)
|
||||
YG_VALUE_PROPERTY(minHeight, MinHeight)
|
||||
YG_VALUE_PROPERTY(maxWidth, MaxWidth)
|
||||
YG_VALUE_PROPERTY(maxHeight, MaxHeight)
|
||||
YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
|
||||
|
||||
#pragma mark - Layout and Sizing
|
||||
|
||||
- (YGDirection)resolvedDirection
|
||||
{
|
||||
return YGNodeLayoutGetDirection(self.node);
|
||||
}
|
||||
|
||||
- (void)applyLayout
|
||||
{
|
||||
[self calculateLayoutWithSize:self.view.bounds.size];
|
||||
YGApplyLayoutToViewHierarchy(self.view, NO);
|
||||
}
|
||||
|
||||
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
|
||||
{
|
||||
[self calculateLayoutWithSize:self.view.bounds.size];
|
||||
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
|
||||
}
|
||||
|
||||
- (CGSize)intrinsicSize
|
||||
{
|
||||
const CGSize constrainedSize = {
|
||||
.width = YGUndefined,
|
||||
.height = YGUndefined,
|
||||
};
|
||||
return [self calculateLayoutWithSize:constrainedSize];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (CGSize)calculateLayoutWithSize:(CGSize)size
|
||||
{
|
||||
NSAssert([NSThread isMainThread], @"Yoga calculation must be done on main.");
|
||||
NSAssert(self.isEnabled, @"Yoga is not enabled for this view.");
|
||||
|
||||
YGAttachNodesFromViewHierachy(self.view);
|
||||
|
||||
const YGNodeRef node = self.node;
|
||||
YGNodeCalculateLayout(
|
||||
node,
|
||||
size.width,
|
||||
size.height,
|
||||
YGNodeStyleGetDirection(node));
|
||||
|
||||
return (CGSize) {
|
||||
.width = YGNodeLayoutGetWidth(node),
|
||||
.height = YGNodeLayoutGetHeight(node),
|
||||
};
|
||||
}
|
||||
|
||||
static YGSize YGMeasureView(
|
||||
YGNodeRef node,
|
||||
float width,
|
||||
YGMeasureMode widthMode,
|
||||
float height,
|
||||
YGMeasureMode heightMode)
|
||||
{
|
||||
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
|
||||
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height;
|
||||
|
||||
UIView *view = (__bridge UIView*) YGNodeGetContext(node);
|
||||
const CGSize sizeThatFits = [view sizeThatFits:(CGSize) {
|
||||
.width = constrainedWidth,
|
||||
.height = constrainedHeight,
|
||||
}];
|
||||
|
||||
return (YGSize) {
|
||||
.width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode),
|
||||
.height = YGSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode),
|
||||
};
|
||||
}
|
||||
|
||||
static CGFloat YGSanitizeMeasurement(
|
||||
CGFloat constrainedSize,
|
||||
CGFloat measuredSize,
|
||||
YGMeasureMode measureMode)
|
||||
{
|
||||
CGFloat result;
|
||||
if (measureMode == YGMeasureModeExactly) {
|
||||
result = constrainedSize;
|
||||
} else if (measureMode == YGMeasureModeAtMost) {
|
||||
result = MIN(constrainedSize, measuredSize);
|
||||
} else {
|
||||
result = measuredSize;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL YGNodeHasExactSameChildren(const YGNodeRef node, NSArray<UIView *> *subviews)
|
||||
{
|
||||
if (YGNodeGetChildCount(node) != subviews.count) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
for (int i=0; i<subviews.count; i++) {
|
||||
if (YGNodeGetChild(node, i) != subviews[i].yoga.node) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
static void YGAttachNodesFromViewHierachy(UIView *const view)
|
||||
{
|
||||
YGLayout *const yoga = view.yoga;
|
||||
const YGNodeRef node = yoga.node;
|
||||
|
||||
// Only leaf nodes should have a measure function
|
||||
if (yoga.isLeaf) {
|
||||
YGRemoveAllChildren(node);
|
||||
YGNodeSetMeasureFunc(node, YGMeasureView);
|
||||
} else {
|
||||
YGNodeSetMeasureFunc(node, NULL);
|
||||
|
||||
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
|
||||
for (UIView *subview in view.subviews) {
|
||||
if (subview.yoga.isIncludedInLayout) {
|
||||
[subviewsToInclude addObject:subview];
|
||||
}
|
||||
}
|
||||
|
||||
if (!YGNodeHasExactSameChildren(node, subviewsToInclude)) {
|
||||
YGRemoveAllChildren(node);
|
||||
for (int i=0; i<subviewsToInclude.count; i++) {
|
||||
YGNodeInsertChild(node, subviewsToInclude[i].yoga.node, i);
|
||||
}
|
||||
}
|
||||
|
||||
for (UIView *const subview in subviewsToInclude) {
|
||||
YGAttachNodesFromViewHierachy(subview);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void YGRemoveAllChildren(const YGNodeRef node)
|
||||
{
|
||||
if (node == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (YGNodeGetChildCount(node) > 0) {
|
||||
YGNodeRemoveChild(node, YGNodeGetChild(node, YGNodeGetChildCount(node) - 1));
|
||||
}
|
||||
}
|
||||
|
||||
static CGFloat YGRoundPixelValue(CGFloat value)
|
||||
{
|
||||
static CGFloat scale;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^(){
|
||||
scale = [UIScreen mainScreen].scale;
|
||||
});
|
||||
|
||||
return roundf(value * scale) / scale;
|
||||
}
|
||||
|
||||
static void YGApplyLayoutToViewHierarchy(UIView *view, BOOL preserveOrigin)
|
||||
{
|
||||
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread.");
|
||||
|
||||
const YGLayout *yoga = view.yoga;
|
||||
|
||||
if (!yoga.isIncludedInLayout) {
|
||||
return;
|
||||
}
|
||||
|
||||
YGNodeRef node = yoga.node;
|
||||
const CGPoint topLeft = {
|
||||
YGNodeLayoutGetLeft(node),
|
||||
YGNodeLayoutGetTop(node),
|
||||
};
|
||||
|
||||
const CGPoint bottomRight = {
|
||||
topLeft.x + YGNodeLayoutGetWidth(node),
|
||||
topLeft.y + YGNodeLayoutGetHeight(node),
|
||||
};
|
||||
|
||||
const CGPoint origin = preserveOrigin ? view.frame.origin : CGPointZero;
|
||||
view.frame = (CGRect) {
|
||||
.origin = {
|
||||
.x = YGRoundPixelValue(topLeft.x + origin.x),
|
||||
.y = YGRoundPixelValue(topLeft.y + origin.y),
|
||||
},
|
||||
.size = {
|
||||
.width = YGRoundPixelValue(bottomRight.x) - YGRoundPixelValue(topLeft.x),
|
||||
.height = YGRoundPixelValue(bottomRight.y) - YGRoundPixelValue(topLeft.y),
|
||||
},
|
||||
};
|
||||
|
||||
if (!yoga.isLeaf) {
|
||||
for (NSUInteger i=0; i<view.subviews.count; i++) {
|
||||
YGApplyLayoutToViewHierarchy(view.subviews[i], NO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@@ -9,91 +9,191 @@
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "UIView+Yoga.h"
|
||||
#import <YogaKit/UIView+Yoga.h>
|
||||
#import <YogaKit/YGLayout+Private.h>
|
||||
#import <yoga/Yoga.h>
|
||||
|
||||
@interface YogaKitTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation YogaKitTests
|
||||
|
||||
#ifndef TRAVIS_CI
|
||||
- (void)testConfigureLayoutIsNoOpWithNilBlock
|
||||
{
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
XCTAssertNoThrow([view configureLayoutWithBlock:nil]);
|
||||
}
|
||||
|
||||
- (void)testConfigureLayoutBlockWorksWithValidBlock
|
||||
{
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[view configureLayoutWithBlock:^(YGLayout *layout){
|
||||
XCTAssertNotNil(layout);
|
||||
layout.isEnabled = YES;
|
||||
layout.width = 25;
|
||||
}];
|
||||
|
||||
XCTAssertTrue(view.yoga.isEnabled);
|
||||
XCTAssertEqual(view.yoga.width, 25);
|
||||
}
|
||||
|
||||
- (void)testNodesAreDeallocedWithSingleView
|
||||
{
|
||||
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
||||
__weak YGLayout *layoutRef = nil;
|
||||
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[view yg_setFlexBasis:1];
|
||||
XCTAssertEqual(1, YGNodeGetInstanceCount());
|
||||
view = nil;
|
||||
@autoreleasepool {
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
view.yoga.flexBasis = 1;
|
||||
|
||||
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
||||
layoutRef = view.yoga;
|
||||
XCTAssertNotNil(layoutRef);
|
||||
|
||||
view = nil;
|
||||
}
|
||||
|
||||
XCTAssertNil(layoutRef);
|
||||
}
|
||||
|
||||
- (void)testNodesAreDeallocedCascade
|
||||
{
|
||||
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
||||
__weak YGLayout *topLayout = nil;
|
||||
__weak YGLayout *subviewLayout = nil;
|
||||
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[view yg_setFlexBasis:1];
|
||||
@autoreleasepool {
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
topLayout = view.yoga;
|
||||
topLayout.flexBasis = 1;
|
||||
|
||||
for (int i=0; i<10; i++) {
|
||||
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview yg_setFlexBasis:1];
|
||||
[view addSubview:subview];
|
||||
}
|
||||
XCTAssertEqual(11, YGNodeGetInstanceCount());
|
||||
view = nil;
|
||||
subviewLayout = subview.yoga;
|
||||
subviewLayout.flexBasis = 1;
|
||||
|
||||
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
||||
view = nil;
|
||||
}
|
||||
|
||||
XCTAssertNil(topLayout);
|
||||
XCTAssertNil(subviewLayout);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (void)testUsesYoga
|
||||
- (void)testIsEnabled
|
||||
{
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
XCTAssertFalse([view yg_usesYoga]);
|
||||
XCTAssertFalse(view.yoga.isEnabled);
|
||||
|
||||
[view yg_setUsesYoga:YES];
|
||||
XCTAssertTrue([view yg_usesYoga]);
|
||||
view.yoga.isEnabled = YES;
|
||||
XCTAssertTrue(view.yoga.isEnabled);
|
||||
|
||||
[view yg_setUsesYoga:NO];
|
||||
XCTAssertFalse([view yg_usesYoga]);
|
||||
view.yoga.isEnabled = NO;
|
||||
XCTAssertFalse(view.yoga.isEnabled);
|
||||
}
|
||||
|
||||
- (void)testSizeThatFitsAsserts
|
||||
{
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
dispatch_sync(dispatch_queue_create("com.facebook.Yoga.testing", DISPATCH_QUEUE_SERIAL), ^(void){
|
||||
XCTAssertThrows([view yg_intrinsicSize]);
|
||||
XCTAssertThrows(view.yoga.intrinsicSize);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)testSizeThatFitsSmoke
|
||||
{
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[container yg_setUsesYoga:YES];
|
||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
||||
[container yg_setAlignItems:YGAlignFlexStart];
|
||||
container.yoga.isEnabled = YES;
|
||||
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||
container.yoga.alignItems = YGAlignFlexStart;
|
||||
|
||||
UILabel *longTextLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
longTextLabel.text = @"This is a very very very very very very very very long piece of text.";
|
||||
longTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
longTextLabel.numberOfLines = 1;
|
||||
[longTextLabel yg_setUsesYoga:YES];
|
||||
[longTextLabel yg_setFlexShrink:1];
|
||||
longTextLabel.yoga.isEnabled = YES;
|
||||
longTextLabel.yoga.flexShrink = 1;
|
||||
[container addSubview:longTextLabel];
|
||||
|
||||
UIView *textBadgeView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[textBadgeView yg_setUsesYoga:YES];
|
||||
[textBadgeView yg_setMargin:3.0 forEdge:YGEdgeLeft];
|
||||
[textBadgeView yg_setWidth:10];
|
||||
[textBadgeView yg_setHeight:10];
|
||||
textBadgeView.yoga.isEnabled = YES;
|
||||
textBadgeView.yoga.margin = 0;
|
||||
textBadgeView.yoga.width = 10;
|
||||
textBadgeView.yoga.height = 10;
|
||||
[container addSubview:textBadgeView];
|
||||
|
||||
const CGSize containerSize = [container yg_intrinsicSize];
|
||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(514,21), containerSize), @"Size is actually %@", NSStringFromCGSize(containerSize));
|
||||
const CGSize textBadgeViewSize = textBadgeView.yoga.intrinsicSize;
|
||||
XCTAssertEqual(textBadgeViewSize.height, 10);
|
||||
XCTAssertEqual(textBadgeViewSize.width, 10);
|
||||
|
||||
const CGSize containerSize = container.yoga.intrinsicSize;
|
||||
const CGSize longTextLabelSize = longTextLabel.yoga.intrinsicSize;
|
||||
|
||||
XCTAssertEqual(longTextLabelSize.height, containerSize.height);
|
||||
XCTAssertEqual(longTextLabelSize.width + textBadgeView.yoga.intrinsicSize.width, containerSize.width);
|
||||
}
|
||||
|
||||
- (void)testPreservingOrigin
|
||||
{
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,75)];
|
||||
container.yoga.isEnabled = YES;
|
||||
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
view.yoga.isEnabled = YES;
|
||||
view.yoga.flexBasis = 0;
|
||||
view.yoga.flexGrow = 1;
|
||||
[container addSubview:view];
|
||||
|
||||
UIView *view2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
view2.yoga.isEnabled = YES;
|
||||
view2.yoga.marginTop = 25;
|
||||
view2.yoga.flexBasis = 0;
|
||||
view2.yoga.flexGrow = 1;
|
||||
[container addSubview:view2];
|
||||
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
XCTAssertEqual(50, view2.frame.origin.y);
|
||||
|
||||
[view2.yoga applyLayoutPreservingOrigin:NO];
|
||||
XCTAssertEqual(25, view2.frame.origin.y);
|
||||
}
|
||||
|
||||
- (void)testMarkingDirtyOnlyWorksOnLeafNodes
|
||||
{
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
container.yoga.isEnabled = YES;
|
||||
|
||||
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
subview.yoga.isEnabled = YES;
|
||||
[container addSubview:subview];
|
||||
|
||||
XCTAssertFalse(container.yoga.isDirty);
|
||||
[container.yoga markDirty];
|
||||
XCTAssertFalse(container.yoga.isDirty);
|
||||
|
||||
XCTAssertFalse(subview.yoga.isDirty);
|
||||
[subview.yoga markDirty];
|
||||
XCTAssertTrue(subview.yoga.isDirty);
|
||||
}
|
||||
|
||||
- (void)testThatMarkingLeafsAsDirtyWillTriggerASizeRecalculation
|
||||
{
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 50)];
|
||||
container.yoga.isEnabled = YES;
|
||||
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||
container.yoga.alignItems = YGAlignFlexStart;
|
||||
|
||||
UILabel *view = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
view.text = @"This is a short text.";
|
||||
view.numberOfLines = 1;
|
||||
view.yoga.isEnabled = YES;
|
||||
[container addSubview:view];
|
||||
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
CGSize const viewSizeAfterFirstPass = view.frame.size;
|
||||
|
||||
view.text = @"This is a slightly longer text.";
|
||||
XCTAssertTrue(CGSizeEqualToSize(view.frame.size, viewSizeAfterFirstPass));
|
||||
|
||||
[view.yoga markDirty];
|
||||
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
XCTAssertFalse(CGSizeEqualToSize(view.frame.size, viewSizeAfterFirstPass));
|
||||
}
|
||||
|
||||
- (void)testFrameAndOriginPlacement
|
||||
@@ -101,21 +201,28 @@
|
||||
const CGSize containerSize = CGSizeMake(320, 50);
|
||||
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
||||
[container yg_setUsesYoga:YES];
|
||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
||||
container.yoga.isEnabled = YES;
|
||||
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview yg_setUsesYoga:YES];
|
||||
[subview yg_setFlexGrow:1];
|
||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
subview1.yoga.isEnabled = YES;
|
||||
subview1.yoga.flexGrow = 1;
|
||||
[container addSubview:subview1];
|
||||
|
||||
[container addSubview:subview];
|
||||
}
|
||||
[container yg_applyLayout];
|
||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
subview2.yoga.isEnabled = YES;
|
||||
subview2.yoga.flexGrow = 1;
|
||||
[container addSubview:subview2];
|
||||
|
||||
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:0].frame, [container.subviews objectAtIndex:1].frame));
|
||||
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:1].frame, [container.subviews objectAtIndex:2].frame));
|
||||
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:0].frame, [container.subviews objectAtIndex:2].frame));
|
||||
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
subview3.yoga.isEnabled = YES;
|
||||
subview3.yoga.flexGrow = 1;
|
||||
[container addSubview:subview3];
|
||||
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
|
||||
XCTAssertEqualWithAccuracy(subview2.frame.origin.x, CGRectGetMaxX(subview1.frame), FLT_EPSILON);
|
||||
XCTAssertEqualWithAccuracy(subview3.frame.origin.x, CGRectGetMaxX(subview2.frame), FLT_EPSILON);
|
||||
|
||||
CGFloat totalWidth = 0;
|
||||
for (UIView *view in container.subviews) {
|
||||
@@ -130,33 +237,33 @@
|
||||
const CGSize containerSize = CGSizeMake(300, 50);
|
||||
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
||||
[container yg_setUsesYoga:YES];
|
||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
||||
container.yoga.isEnabled = YES;
|
||||
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||
|
||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview1 yg_setUsesYoga:YES];
|
||||
[subview1 yg_setFlexGrow:1];
|
||||
subview1.yoga.isEnabled = YES;
|
||||
subview1.yoga.flexGrow = 1;
|
||||
[container addSubview:subview1];
|
||||
|
||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview2 yg_setUsesYoga:YES];
|
||||
[subview2 yg_setFlexGrow:1];
|
||||
subview2.yoga.isEnabled = YES;
|
||||
subview2.yoga.flexGrow = 1;
|
||||
[container addSubview:subview2];
|
||||
|
||||
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview3 yg_setUsesYoga:YES];
|
||||
[subview3 yg_setFlexGrow:1];
|
||||
subview3.yoga.isEnabled = YES;
|
||||
subview3.yoga.flexGrow = 1;
|
||||
[container addSubview:subview3];
|
||||
|
||||
[container yg_applyLayout];
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
|
||||
XCTAssertTrue(CGRectEqualToRect(subview1.frame, CGRectMake(0, 0, 100, 50)));
|
||||
XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50)), @"It's actually %@", NSStringFromCGRect(subview2.frame));
|
||||
XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50)));
|
||||
XCTAssertTrue(CGRectEqualToRect(subview3.frame, CGRectMake(200, 0, 100, 50)));
|
||||
|
||||
[container exchangeSubviewAtIndex:2 withSubviewAtIndex:0];
|
||||
[subview2 yg_setIncludeInLayout:NO];
|
||||
[container yg_applyLayout];
|
||||
subview2.yoga.isIncludedInLayout = NO;
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
|
||||
XCTAssertTrue(CGRectEqualToRect(subview3.frame, CGRectMake(0, 0, 150, 50)));
|
||||
XCTAssertTrue(CGRectEqualToRect(subview1.frame, CGRectMake(150, 0, 150, 50)));
|
||||
@@ -170,102 +277,383 @@
|
||||
const CGSize containerSize = CGSizeMake(300, 50);
|
||||
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
||||
[container yg_setUsesYoga:YES];
|
||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
||||
container.yoga.isEnabled = YES;
|
||||
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||
|
||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview1 yg_setUsesYoga:YES];
|
||||
[subview1 yg_setFlexGrow:1];
|
||||
subview1.yoga.isEnabled = YES;
|
||||
subview1.yoga.flexGrow = 1;
|
||||
[container addSubview:subview1];
|
||||
|
||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview2 yg_setUsesYoga:YES];
|
||||
[subview2 yg_setFlexGrow:1];
|
||||
subview2.yoga.isEnabled = YES;
|
||||
subview2.yoga.flexGrow = 1;
|
||||
[container addSubview:subview2];
|
||||
|
||||
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview3 yg_setUsesYoga:YES];
|
||||
[subview3 yg_setFlexGrow:1];
|
||||
subview3.yoga.isEnabled = YES;
|
||||
subview3.yoga.flexGrow = 1;
|
||||
[container addSubview:subview3];
|
||||
|
||||
[container yg_applyLayout];
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
|
||||
for (UIView *view in container.subviews) {
|
||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(view.bounds.size));
|
||||
for (UIView *subview in container.subviews) {
|
||||
XCTAssertEqual(subview.bounds.size.width, 100);
|
||||
}
|
||||
|
||||
[subview3 yg_setIncludeInLayout:NO];
|
||||
[container yg_applyLayout];
|
||||
subview3.yoga.isIncludedInLayout = NO;
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
|
||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview1.bounds.size));
|
||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size));
|
||||
XCTAssertEqual(subview1.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.
|
||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview3.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview3.bounds.size));
|
||||
XCTAssertEqual(subview3.bounds.size.width, 100);
|
||||
}
|
||||
|
||||
- (void)testThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews
|
||||
{
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[container yg_setUsesYoga:YES];
|
||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
||||
container.yoga.isEnabled = YES;
|
||||
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||
|
||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview1 yg_setUsesYoga:YES];
|
||||
[subview1 yg_setIncludeInLayout:NO];
|
||||
subview1.yoga.isEnabled = YES;
|
||||
subview1.yoga.isIncludedInLayout = NO;
|
||||
[container addSubview:subview1];
|
||||
|
||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview2 yg_setUsesYoga:YES];
|
||||
[subview2 yg_setIncludeInLayout:NO];
|
||||
subview2.yoga.isEnabled = YES;
|
||||
subview2.yoga.isIncludedInLayout = NO;
|
||||
[container addSubview:subview2];
|
||||
|
||||
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview3 yg_setUsesYoga:YES];
|
||||
[subview3 yg_setIncludeInLayout:YES];
|
||||
subview3.yoga.isEnabled = YES;
|
||||
subview3.yoga.isIncludedInLayout = YES;
|
||||
[container addSubview:subview3];
|
||||
|
||||
[container yg_applyLayout];
|
||||
XCTAssertEqual(1, [container yg_numberOfChildren]);
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
XCTAssertEqual(container.yoga.numberOfChildren, 1);
|
||||
|
||||
[subview2 yg_setIncludeInLayout:YES];
|
||||
[container yg_applyLayout];
|
||||
XCTAssertEqual(2, [container yg_numberOfChildren]);
|
||||
subview2.yoga.isIncludedInLayout = YES;
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
XCTAssertEqual(container.yoga.numberOfChildren, 2);
|
||||
}
|
||||
|
||||
- (void)testThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond
|
||||
{
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
|
||||
[container yg_setUsesYoga:YES];
|
||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
||||
container.yoga.isEnabled = YES;
|
||||
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||
|
||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview1 yg_setUsesYoga:YES];
|
||||
[subview1 yg_setFlexGrow:1];
|
||||
subview1.yoga.isEnabled = YES;
|
||||
subview1.yoga.flexGrow = 1;
|
||||
[container addSubview:subview1];
|
||||
|
||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview2 yg_setUsesYoga:YES];
|
||||
[subview2 yg_setFlexGrow:1];
|
||||
subview2.yoga.isEnabled = YES;
|
||||
subview2.yoga.flexGrow = 1;
|
||||
[container addSubview:subview2];
|
||||
|
||||
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[subview3 yg_setUsesYoga:YES];
|
||||
[subview3 yg_setFlexGrow:1];
|
||||
[subview3 yg_setIncludeInLayout:NO];
|
||||
subview3.yoga.isEnabled = YES;
|
||||
subview3.yoga.flexGrow = 1;
|
||||
subview3.yoga.isIncludedInLayout = NO;
|
||||
[container addSubview:subview3];
|
||||
|
||||
[container yg_applyLayout];
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
|
||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview1.bounds.size));
|
||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size));
|
||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeZero, subview3.bounds.size), @"Actual size %@", NSStringFromCGSize(subview3.bounds.size));
|
||||
XCTAssertEqual(subview1.bounds.size.width, 150);
|
||||
XCTAssertEqual(subview2.bounds.size.width, 150);
|
||||
XCTAssertEqual(subview3.bounds.size.width, 0);
|
||||
|
||||
[subview3 yg_setIncludeInLayout:YES];
|
||||
[container yg_applyLayout];
|
||||
for (UIView *view in container.subviews) {
|
||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(view.bounds.size));
|
||||
subview3.yoga.isIncludedInLayout = YES;
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
|
||||
XCTAssertEqual(subview1.bounds.size.width, 100);
|
||||
XCTAssertEqual(subview2.bounds.size.width, 100);
|
||||
XCTAssertEqual(subview3.bounds.size.width, 100);
|
||||
}
|
||||
|
||||
- (void)testIsLeafFlag
|
||||
{
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
XCTAssertTrue(view.yoga.isLeaf);
|
||||
|
||||
for (int i=0; i<10; i++) {
|
||||
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[view addSubview:subview];
|
||||
}
|
||||
XCTAssertTrue(view.yoga.isLeaf);
|
||||
|
||||
view.yoga.isEnabled = YES;
|
||||
view.yoga.width = 50.0;
|
||||
XCTAssertTrue(view.yoga.isLeaf);
|
||||
|
||||
UIView *const subview = view.subviews[0];
|
||||
subview.yoga.isEnabled = YES;
|
||||
subview.yoga.width = 50.0;
|
||||
XCTAssertFalse(view.yoga.isLeaf);
|
||||
}
|
||||
|
||||
- (void)testThatWeCorrectlyAttachNestedViews
|
||||
{
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
|
||||
container.yoga.isEnabled = YES;
|
||||
container.yoga.flexDirection = YGFlexDirectionColumn;
|
||||
|
||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
subview1.yoga.isEnabled = YES;
|
||||
subview1.yoga.width = 100;
|
||||
subview1.yoga.flexGrow = 1;
|
||||
subview1.yoga.flexDirection = YGFlexDirectionColumn;
|
||||
[container addSubview:subview1];
|
||||
|
||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
subview2.yoga.isEnabled = YES;
|
||||
subview2.yoga.width = 150;
|
||||
subview2.yoga.flexGrow = 1;
|
||||
subview2.yoga.flexDirection = YGFlexDirectionColumn;
|
||||
[container addSubview:subview2];
|
||||
|
||||
for (UIView *view in @[subview1, subview2]) {
|
||||
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
someView.yoga.isEnabled = YES;
|
||||
someView.yoga.flexGrow = 1;
|
||||
[view addSubview:someView];
|
||||
}
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
|
||||
// Add the same amount of new views, reapply layout.
|
||||
for (UIView *view in @[subview1, subview2]) {
|
||||
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
someView.yoga.isEnabled = YES;
|
||||
someView.yoga.flexGrow = 1;
|
||||
[view addSubview:someView];
|
||||
}
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
|
||||
XCTAssertEqual(subview1.bounds.size.width, 100);
|
||||
XCTAssertEqual(subview1.bounds.size.height, 25);
|
||||
for (UIView *subview in subview1.subviews) {
|
||||
const CGSize subviewSize = subview.bounds.size;
|
||||
XCTAssertNotEqual(subviewSize.width, 0);
|
||||
XCTAssertNotEqual(subviewSize.height, 0);
|
||||
XCTAssertFalse(isnan(subviewSize.height));
|
||||
XCTAssertFalse(isnan(subviewSize.width));
|
||||
}
|
||||
|
||||
XCTAssertEqual(subview2.bounds.size.width, 150);
|
||||
XCTAssertEqual(subview2.bounds.size.height, 25);
|
||||
for (UIView *subview in subview2.subviews) {
|
||||
const CGSize subviewSize = subview.bounds.size;
|
||||
XCTAssertNotEqual(subviewSize.width, 0);
|
||||
XCTAssertNotEqual(subviewSize.height, 0);
|
||||
XCTAssertFalse(isnan(subviewSize.height));
|
||||
XCTAssertFalse(isnan(subviewSize.width));
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testThatANonLeafNodeCanBecomeALeafNode
|
||||
{
|
||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
|
||||
container.yoga.isEnabled = YES;
|
||||
|
||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
subview1.yoga.isEnabled = YES;
|
||||
[container addSubview:subview1];
|
||||
|
||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
subview2.yoga.isEnabled = YES;
|
||||
[subview1 addSubview:subview2];
|
||||
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
[subview2 removeFromSuperview];
|
||||
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||
}
|
||||
|
||||
- (void)testPositionalPropertiesWork
|
||||
{
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
|
||||
view.yoga.left = 1;
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeLeft).value, 1);
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeLeft).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.left, 1);
|
||||
|
||||
view.yoga.right = 2;
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeRight).value, 2);
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeRight).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.right, 2);
|
||||
|
||||
view.yoga.top = 3;
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeTop).value, 3);
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeTop).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.top, 3);
|
||||
|
||||
view.yoga.bottom = 4;
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeBottom).value, 4);
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeBottom).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.bottom, 4);
|
||||
|
||||
view.yoga.start = 5;
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeStart).value, 5);
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeStart).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.start, 5);
|
||||
|
||||
view.yoga.end = 6;
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeEnd).value, 6);
|
||||
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeEnd).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.end, 6);
|
||||
}
|
||||
|
||||
- (void)testMarginPropertiesWork
|
||||
{
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
|
||||
view.yoga.margin = 1;
|
||||
XCTAssertEqual(view.yoga.margin, 1);
|
||||
XCTAssertTrue(isnan(view.yoga.marginLeft));
|
||||
XCTAssertTrue(isnan(view.yoga.marginRight));
|
||||
XCTAssertTrue(isnan(view.yoga.marginStart));
|
||||
XCTAssertTrue(isnan(view.yoga.marginEnd));
|
||||
XCTAssertTrue(isnan(view.yoga.marginTop));
|
||||
XCTAssertTrue(isnan(view.yoga.marginBottom));
|
||||
XCTAssertTrue(isnan(view.yoga.marginHorizontal));
|
||||
XCTAssertTrue(isnan(view.yoga.marginVertical));
|
||||
|
||||
view.yoga.marginHorizontal = 2;
|
||||
XCTAssertEqual(view.yoga.marginHorizontal, 2);
|
||||
XCTAssertTrue(isnan(view.yoga.marginLeft));
|
||||
XCTAssertTrue(isnan(view.yoga.marginRight));
|
||||
XCTAssertTrue(isnan(view.yoga.marginStart));
|
||||
XCTAssertTrue(isnan(view.yoga.marginEnd));
|
||||
|
||||
view.yoga.marginVertical = 3;
|
||||
XCTAssertEqual(view.yoga.marginVertical, 3);
|
||||
XCTAssertTrue(isnan(view.yoga.marginTop));
|
||||
XCTAssertTrue(isnan(view.yoga.marginBottom));
|
||||
|
||||
view.yoga.marginLeft = 4;
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeLeft).value, 4);
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeLeft).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.marginLeft, 4);
|
||||
|
||||
view.yoga.marginRight = 5;
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeRight).value, 5);
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeRight).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.marginRight, 5);
|
||||
|
||||
view.yoga.marginTop = 6;
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeTop).value, 6);
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeTop).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.marginTop, 6);
|
||||
|
||||
view.yoga.marginBottom = 7;
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeBottom).value, 7);
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeBottom).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.marginBottom, 7);
|
||||
|
||||
view.yoga.marginStart = 8;
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeStart).value, 8);
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeStart).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.marginStart, 8);
|
||||
|
||||
view.yoga.marginEnd = 9;
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeEnd).value, 9);
|
||||
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeEnd).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.marginEnd, 9);
|
||||
}
|
||||
|
||||
- (void)testPaddingPropertiesWork
|
||||
{
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
|
||||
view.yoga.padding = 1;
|
||||
XCTAssertEqual(view.yoga.padding, 1);
|
||||
XCTAssertTrue(isnan(view.yoga.paddingLeft));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingRight));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingStart));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingEnd));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingTop));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingBottom));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingHorizontal));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingVertical));
|
||||
|
||||
view.yoga.paddingHorizontal = 2;
|
||||
XCTAssertEqual(view.yoga.paddingHorizontal, 2);
|
||||
XCTAssertTrue(isnan(view.yoga.paddingLeft));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingRight));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingStart));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingEnd));
|
||||
|
||||
view.yoga.paddingVertical = 3;
|
||||
XCTAssertEqual(view.yoga.paddingVertical, 3);
|
||||
XCTAssertTrue(isnan(view.yoga.paddingTop));
|
||||
XCTAssertTrue(isnan(view.yoga.paddingBottom));
|
||||
|
||||
view.yoga.paddingLeft = 4;
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeLeft).value, 4);
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeLeft).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.paddingLeft, 4);
|
||||
|
||||
view.yoga.paddingRight = 5;
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeRight).value, 5);
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeRight).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.paddingRight, 5);
|
||||
|
||||
view.yoga.paddingTop = 6;
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeTop).value, 6);
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeTop).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.paddingTop, 6);
|
||||
|
||||
view.yoga.paddingBottom = 7;
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeBottom).value, 7);
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeBottom).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.paddingBottom, 7);
|
||||
|
||||
view.yoga.paddingStart = 8;
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeStart).value, 8);
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeStart).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.paddingStart, 8);
|
||||
|
||||
view.yoga.paddingEnd = 9;
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeEnd).value, 9);
|
||||
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeEnd).unit, YGUnitPoint);
|
||||
XCTAssertEqual(view.yoga.paddingEnd, 9);
|
||||
}
|
||||
|
||||
- (void)testBorderWidthPropertiesWork
|
||||
{
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
|
||||
view.yoga.borderWidth = 1;
|
||||
XCTAssertEqual(view.yoga.borderWidth, 1);
|
||||
XCTAssertTrue(isnan(view.yoga.borderLeftWidth));
|
||||
XCTAssertTrue(isnan(view.yoga.borderRightWidth));
|
||||
XCTAssertTrue(isnan(view.yoga.borderStartWidth));
|
||||
XCTAssertTrue(isnan(view.yoga.borderEndWidth));
|
||||
XCTAssertTrue(isnan(view.yoga.borderTopWidth));
|
||||
XCTAssertTrue(isnan(view.yoga.borderBottomWidth));
|
||||
|
||||
view.yoga.borderLeftWidth = 2;
|
||||
XCTAssertEqual(view.yoga.borderLeftWidth, 2);
|
||||
|
||||
view.yoga.borderRightWidth = 3;
|
||||
XCTAssertEqual(view.yoga.borderRightWidth, 3);
|
||||
|
||||
view.yoga.borderTopWidth = 4;
|
||||
XCTAssertEqual(view.yoga.borderTopWidth, 4);
|
||||
|
||||
view.yoga.borderBottomWidth = 5;
|
||||
XCTAssertEqual(view.yoga.borderBottomWidth, 5);
|
||||
|
||||
view.yoga.borderStartWidth = 6;
|
||||
XCTAssertEqual(view.yoga.borderStartWidth, 6);
|
||||
|
||||
view.yoga.borderEndWidth = 7;
|
||||
XCTAssertEqual(view.yoga.borderEndWidth, 7);
|
||||
}
|
||||
|
||||
@end
|
||||
|
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <CSSLayout/Yoga.h>
|
||||
|
||||
@interface UIView (Yoga)
|
||||
|
||||
/**
|
||||
The property that decides if we should include this view when calculating layout. Defaults to YES.
|
||||
*/
|
||||
@property (nonatomic, readwrite, assign, setter=yg_setIncludeInLayout:) BOOL yg_includeInLayout;
|
||||
|
||||
/**
|
||||
The property that decides during layout/sizing whether or not yg_* properties should be applied. Defaults to NO.
|
||||
*/
|
||||
@property (nonatomic, readwrite, assign, setter=yg_setUsesYoga:) BOOL yg_usesYoga;
|
||||
|
||||
- (void)yg_setDirection:(YGDirection)direction;
|
||||
- (void)yg_setFlexDirection:(YGFlexDirection)flexDirection;
|
||||
- (void)yg_setJustifyContent:(YGJustify)justifyContent;
|
||||
- (void)yg_setAlignContent:(YGAlign)alignContent;
|
||||
- (void)yg_setAlignItems:(YGAlign)alignItems;
|
||||
- (void)yg_setAlignSelf:(YGAlign)alignSelf;
|
||||
- (void)yg_setPositionType:(YGPositionType)positionType;
|
||||
- (void)yg_setFlexWrap:(YGWrap)flexWrap;
|
||||
|
||||
- (void)yg_setFlexGrow:(CGFloat)flexGrow;
|
||||
- (void)yg_setFlexShrink:(CGFloat)flexShrink;
|
||||
- (void)yg_setFlexBasis:(CGFloat)flexBasis;
|
||||
|
||||
- (void)yg_setPosition:(CGFloat)position forEdge:(YGEdge)edge;
|
||||
- (void)yg_setMargin:(CGFloat)margin forEdge:(YGEdge)edge;
|
||||
- (void)yg_setPadding:(CGFloat)padding forEdge:(YGEdge)edge;
|
||||
|
||||
- (void)yg_setWidth:(CGFloat)width;
|
||||
- (void)yg_setHeight:(CGFloat)height;
|
||||
- (void)yg_setMinWidth:(CGFloat)minWidth;
|
||||
- (void)yg_setMinHeight:(CGFloat)minHeight;
|
||||
- (void)yg_setMaxWidth:(CGFloat)maxWidth;
|
||||
- (void)yg_setMaxHeight:(CGFloat)maxHeight;
|
||||
|
||||
// Yoga specific properties, not compatible with flexbox specification
|
||||
- (void)yg_setAspectRatio:(CGFloat)aspectRatio;
|
||||
|
||||
/**
|
||||
Get the resolved direction of this node. This won't be YGDirectionInherit
|
||||
*/
|
||||
- (YGDirection)yg_resolvedDirection;
|
||||
|
||||
/**
|
||||
Perform a layout calculation and update the frames of the views in the hierarchy with th results
|
||||
*/
|
||||
- (void)yg_applyLayout;
|
||||
|
||||
/**
|
||||
Returns the size of the view if no constraints were given. This could equivalent to calling [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||
*/
|
||||
- (CGSize)yg_intrinsicSize;
|
||||
|
||||
/**
|
||||
Returns the number of children that are using Flexbox.
|
||||
*/
|
||||
- (NSUInteger)yg_numberOfChildren;
|
||||
|
||||
@end
|
@@ -1,379 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "UIView+Yoga.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@interface YGNodeBridge : NSObject
|
||||
@property (nonatomic, assign, readonly) YGNodeRef cnode;
|
||||
@end
|
||||
|
||||
@implementation YGNodeBridge
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
YogaSetExperimentalFeatureEnabled(YGExperimentalFeatureWebFlexBasis, true);
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ([super init]) {
|
||||
_cnode = YGNodeNew();
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
YGNodeFree(_cnode);
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation UIView (Yoga)
|
||||
|
||||
- (BOOL)yg_usesYoga
|
||||
{
|
||||
NSNumber *usesYoga = objc_getAssociatedObject(self, @selector(yg_usesYoga));
|
||||
return [usesYoga boolValue];
|
||||
}
|
||||
|
||||
- (BOOL)yg_includeInLayout
|
||||
{
|
||||
NSNumber *includeInLayout = objc_getAssociatedObject(self, @selector(yg_includeInLayout));
|
||||
return (includeInLayout != nil) ? [includeInLayout boolValue] : YES;
|
||||
}
|
||||
|
||||
- (NSUInteger)yg_numberOfChildren
|
||||
{
|
||||
return YGNodeChildCount([self ygNode]);
|
||||
}
|
||||
|
||||
#pragma mark - Setters
|
||||
|
||||
- (void)yg_setIncludeInLayout:(BOOL)includeInLayout
|
||||
{
|
||||
objc_setAssociatedObject(
|
||||
self,
|
||||
@selector(yg_includeInLayout),
|
||||
@(includeInLayout),
|
||||
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)yg_setUsesYoga:(BOOL)enabled
|
||||
{
|
||||
objc_setAssociatedObject(
|
||||
self,
|
||||
@selector(yg_usesYoga),
|
||||
@(enabled),
|
||||
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)yg_setDirection:(YGDirection)direction
|
||||
{
|
||||
YGNodeStyleSetDirection([self ygNode], direction);
|
||||
}
|
||||
|
||||
- (void)yg_setFlexDirection:(YGFlexDirection)flexDirection
|
||||
{
|
||||
YGNodeStyleSetFlexDirection([self ygNode], flexDirection);
|
||||
}
|
||||
|
||||
- (void)yg_setJustifyContent:(YGJustify)justifyContent
|
||||
{
|
||||
YGNodeStyleSetJustifyContent([self ygNode], justifyContent);
|
||||
}
|
||||
|
||||
- (void)yg_setAlignContent:(YGAlign)alignContent
|
||||
{
|
||||
YGNodeStyleSetAlignContent([self ygNode], alignContent);
|
||||
}
|
||||
|
||||
- (void)yg_setAlignItems:(YGAlign)alignItems
|
||||
{
|
||||
YGNodeStyleSetAlignItems([self ygNode], alignItems);
|
||||
}
|
||||
|
||||
- (void)yg_setAlignSelf:(YGAlign)alignSelf
|
||||
{
|
||||
YGNodeStyleSetAlignSelf([self ygNode], alignSelf);
|
||||
}
|
||||
|
||||
- (void)yg_setPositionType:(YGPositionType)positionType
|
||||
{
|
||||
YGNodeStyleSetPositionType([self ygNode], positionType);
|
||||
}
|
||||
|
||||
- (void)yg_setFlexWrap:(YGWrap)flexWrap
|
||||
{
|
||||
YGNodeStyleSetFlexWrap([self ygNode], flexWrap);
|
||||
}
|
||||
|
||||
- (void)yg_setFlexGrow:(CGFloat)flexGrow
|
||||
{
|
||||
YGNodeStyleSetFlexGrow([self ygNode], flexGrow);
|
||||
}
|
||||
|
||||
- (void)yg_setFlexShrink:(CGFloat)flexShrink
|
||||
{
|
||||
YGNodeStyleSetFlexShrink([self ygNode], flexShrink);
|
||||
}
|
||||
|
||||
- (void)yg_setFlexBasis:(CGFloat)flexBasis
|
||||
{
|
||||
YGNodeStyleSetFlexBasis([self ygNode], flexBasis);
|
||||
}
|
||||
|
||||
- (void)yg_setPosition:(CGFloat)position forEdge:(YGEdge)edge
|
||||
{
|
||||
YGNodeStyleSetPosition([self ygNode], edge, position);
|
||||
}
|
||||
|
||||
- (void)yg_setMargin:(CGFloat)margin forEdge:(YGEdge)edge
|
||||
{
|
||||
YGNodeStyleSetMargin([self ygNode], edge, margin);
|
||||
}
|
||||
|
||||
- (void)yg_setPadding:(CGFloat)padding forEdge:(YGEdge)edge
|
||||
{
|
||||
YGNodeStyleSetPadding([self ygNode], edge, padding);
|
||||
}
|
||||
|
||||
- (void)yg_setWidth:(CGFloat)width
|
||||
{
|
||||
YGNodeStyleSetWidth([self ygNode], width);
|
||||
}
|
||||
|
||||
- (void)yg_setHeight:(CGFloat)height
|
||||
{
|
||||
YGNodeStyleSetHeight([self ygNode], height);
|
||||
}
|
||||
|
||||
- (void)yg_setMinWidth:(CGFloat)minWidth
|
||||
{
|
||||
YGNodeStyleSetMinWidth([self ygNode], minWidth);
|
||||
}
|
||||
|
||||
- (void)yg_setMinHeight:(CGFloat)minHeight
|
||||
{
|
||||
YGNodeStyleSetMinHeight([self ygNode], minHeight);
|
||||
}
|
||||
|
||||
- (void)yg_setMaxWidth:(CGFloat)maxWidth
|
||||
{
|
||||
YGNodeStyleSetMaxWidth([self ygNode], maxWidth);
|
||||
}
|
||||
|
||||
- (void)yg_setMaxHeight:(CGFloat)maxHeight
|
||||
{
|
||||
YGNodeStyleSetMaxHeight([self ygNode], maxHeight);
|
||||
}
|
||||
|
||||
- (void)yg_setAspectRatio:(CGFloat)aspectRatio
|
||||
{
|
||||
YGNodeStyleSetAspectRatio([self ygNode], aspectRatio);
|
||||
}
|
||||
|
||||
#pragma mark - Layout and Sizing
|
||||
|
||||
- (YGDirection)yg_resolvedDirection
|
||||
{
|
||||
return YGNodeLayoutGetDirection([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yg_applyLayout
|
||||
{
|
||||
[self calculateLayoutWithSize:self.bounds.size];
|
||||
YGApplyLayoutToViewHierarchy(self);
|
||||
}
|
||||
|
||||
- (CGSize)yg_intrinsicSize
|
||||
{
|
||||
const CGSize constrainedSize = {
|
||||
.width = YGUndefined,
|
||||
.height = YGUndefined,
|
||||
};
|
||||
return [self calculateLayoutWithSize:constrainedSize];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (YGNodeRef)ygNode
|
||||
{
|
||||
YGNodeBridge *node = objc_getAssociatedObject(self, @selector(ygNode));
|
||||
if (!node) {
|
||||
node = [YGNodeBridge new];
|
||||
YGNodeSetContext(node.cnode, (__bridge void *) self);
|
||||
objc_setAssociatedObject(self, @selector(ygNode), node, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
return node.cnode;
|
||||
}
|
||||
|
||||
- (CGSize)calculateLayoutWithSize:(CGSize)size
|
||||
{
|
||||
NSAssert([NSThread isMainThread], @"YG Layout calculation must be done on main.");
|
||||
NSAssert([self yg_usesYoga], @"YG Layout is not enabled for this view.");
|
||||
|
||||
YGAttachNodesFromViewHierachy(self);
|
||||
|
||||
const YGNodeRef node = [self ygNode];
|
||||
YGNodeCalculateLayout(
|
||||
node,
|
||||
size.width,
|
||||
size.height,
|
||||
YGNodeStyleGetDirection(node));
|
||||
|
||||
return (CGSize) {
|
||||
.width = YGNodeLayoutGetWidth(node),
|
||||
.height = YGNodeLayoutGetHeight(node),
|
||||
};
|
||||
}
|
||||
|
||||
static YGSize YGMeasureView(
|
||||
YGNodeRef node,
|
||||
float width,
|
||||
YGMeasureMode widthMode,
|
||||
float height,
|
||||
YGMeasureMode heightMode)
|
||||
{
|
||||
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
|
||||
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height;
|
||||
|
||||
UIView *view = (__bridge UIView*) YGNodeGetContext(node);
|
||||
const CGSize sizeThatFits = [view sizeThatFits:(CGSize) {
|
||||
.width = constrainedWidth,
|
||||
.height = constrainedHeight,
|
||||
}];
|
||||
|
||||
return (YGSize) {
|
||||
.width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode),
|
||||
.height = YGSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode),
|
||||
};
|
||||
}
|
||||
|
||||
static CGFloat YGSanitizeMeasurement(
|
||||
CGFloat constrainedSize,
|
||||
CGFloat measuredSize,
|
||||
YGMeasureMode measureMode)
|
||||
{
|
||||
CGFloat result;
|
||||
if (measureMode == YGMeasureModeExactly) {
|
||||
result = constrainedSize;
|
||||
} else if (measureMode == YGMeasureModeAtMost) {
|
||||
result = MIN(constrainedSize, measuredSize);
|
||||
} else {
|
||||
result = measuredSize;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void YGAttachNodesFromViewHierachy(UIView *view) {
|
||||
YGNodeRef node = [view ygNode];
|
||||
|
||||
// Only leaf nodes should have a measure function
|
||||
if (![view yg_usesYoga] || view.subviews.count == 0) {
|
||||
YGNodeSetMeasureFunc(node, YGMeasureView);
|
||||
YGRemoveAllChildren(node);
|
||||
} else {
|
||||
YGNodeSetMeasureFunc(node, NULL);
|
||||
|
||||
// Create a list of all the subviews that we are going to use for layout.
|
||||
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
|
||||
for (UIView *subview in view.subviews) {
|
||||
if ([subview yg_includeInLayout]) {
|
||||
[subviewsToInclude addObject:subview];
|
||||
}
|
||||
}
|
||||
|
||||
BOOL shouldReconstructChildList = NO;
|
||||
if (YGNodeChildCount(node) != subviewsToInclude.count) {
|
||||
shouldReconstructChildList = YES;
|
||||
} else {
|
||||
for (int i = 0; i < subviewsToInclude.count; i++) {
|
||||
if (YGNodeGetChild(node, i) != [subviewsToInclude[i] ygNode]) {
|
||||
shouldReconstructChildList = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldReconstructChildList) {
|
||||
YGRemoveAllChildren(node);
|
||||
|
||||
for (int i = 0 ; i < subviewsToInclude.count; i++) {
|
||||
UIView *const subview = subviewsToInclude[i];
|
||||
YGNodeInsertChild(node, [subview ygNode], i);
|
||||
YGAttachNodesFromViewHierachy(subview);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void YGRemoveAllChildren(const YGNodeRef node)
|
||||
{
|
||||
if (node == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (YGNodeChildCount(node) > 0) {
|
||||
YGNodeRemoveChild(node, YGNodeGetChild(node, YGNodeChildCount(node) - 1));
|
||||
}
|
||||
}
|
||||
|
||||
static CGFloat YGRoundPixelValue(CGFloat value)
|
||||
{
|
||||
static CGFloat scale;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^(){
|
||||
scale = [UIScreen mainScreen].scale;
|
||||
});
|
||||
|
||||
return round(value * scale) / scale;
|
||||
}
|
||||
|
||||
static void YGApplyLayoutToViewHierarchy(UIView *view) {
|
||||
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread.");
|
||||
if (![view yg_includeInLayout]) {
|
||||
return;
|
||||
}
|
||||
|
||||
YGNodeRef node = [view ygNode];
|
||||
const CGPoint topLeft = {
|
||||
YGNodeLayoutGetLeft(node),
|
||||
YGNodeLayoutGetTop(node),
|
||||
};
|
||||
|
||||
const CGPoint bottomRight = {
|
||||
topLeft.x + YGNodeLayoutGetWidth(node),
|
||||
topLeft.y + YGNodeLayoutGetHeight(node),
|
||||
};
|
||||
|
||||
view.frame = (CGRect) {
|
||||
.origin = {
|
||||
.x = YGRoundPixelValue(topLeft.x),
|
||||
.y = YGRoundPixelValue(topLeft.y),
|
||||
},
|
||||
.size = {
|
||||
.width = YGRoundPixelValue(bottomRight.x) - YGRoundPixelValue(topLeft.x),
|
||||
.height = YGRoundPixelValue(bottomRight.y) - YGRoundPixelValue(topLeft.y),
|
||||
},
|
||||
};
|
||||
|
||||
const BOOL isLeaf = ![view yg_usesYoga] || view.subviews.count == 0;
|
||||
if (!isLeaf) {
|
||||
for (NSUInteger i = 0; i < view.subviews.count; i++) {
|
||||
YGApplyLayoutToViewHierarchy(view.subviews[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
6
YogaKit/YogaKitSample/Podfile
Normal file
@@ -0,0 +1,6 @@
|
||||
use_frameworks!
|
||||
|
||||
target 'YogaKitSample' do
|
||||
pod 'YogaKit', :path => '../../YogaKit.podspec'
|
||||
pod 'IGListKit', '~> 2.1.0'
|
||||
end
|
26
YogaKit/YogaKitSample/Podfile.lock
Normal file
@@ -0,0 +1,26 @@
|
||||
PODS:
|
||||
- IGListKit (2.1.0):
|
||||
- IGListKit/Default (= 2.1.0)
|
||||
- IGListKit/Default (2.1.0):
|
||||
- IGListKit/Diffing
|
||||
- IGListKit/Diffing (2.1.0)
|
||||
- Yoga (1.1.0)
|
||||
- YogaKit (1.1.0):
|
||||
- Yoga (~> 1.1)
|
||||
|
||||
DEPENDENCIES:
|
||||
- IGListKit (~> 2.1.0)
|
||||
- YogaKit (from `../../YogaKit.podspec`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
YogaKit:
|
||||
:path: ../../YogaKit.podspec
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
IGListKit: b826c68ef7a4ae1626c09d4d3e1ea7a169e6c36e
|
||||
Yoga: 0bf083b7c485b20598020dbedcea869cbe53071e
|
||||
YogaKit: 80df90de9ef2900baa111f2c93476a6f9e921385
|
||||
|
||||
PODFILE CHECKSUM: 216f8e7127767709e0e43f3711208d238fa5c404
|
||||
|
||||
COCOAPODS: 1.2.0
|
522
YogaKit/YogaKitSample/YogaKitSample.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,522 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
13687D531DF8748400E7C260 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13687D521DF8748400E7C260 /* Assets.xcassets */; };
|
||||
13687D851DF87D1E00E7C260 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13687D841DF87D1E00E7C260 /* UIKit.framework */; };
|
||||
13687D871DF87D2400E7C260 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13687D861DF87D2400E7C260 /* Foundation.framework */; };
|
||||
15A7CB5995C9DAB1C8803834 /* Pods_YogaKitSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C80A931E90C7F3088CB86822 /* Pods_YogaKitSample.framework */; };
|
||||
40BD9F461E477A09002790A9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BD9F451E477A09002790A9 /* AppDelegate.swift */; };
|
||||
40BD9F4B1E47850C002790A9 /* BasicViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BD9F4A1E47850C002790A9 /* BasicViewController.swift */; };
|
||||
40BD9F501E479079002790A9 /* SingleLabelCollectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BD9F4F1E479079002790A9 /* SingleLabelCollectionCell.swift */; };
|
||||
40BD9F521E479173002790A9 /* LayoutInclusionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BD9F511E479173002790A9 /* LayoutInclusionViewController.swift */; };
|
||||
638A94481E1F06D100A726AD /* ExamplesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638A94471E1F06D100A726AD /* ExamplesViewController.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
638A94541E215CC800A726AD /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13687D3B1DF8748300E7C260 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 13687D421DF8748300E7C260;
|
||||
remoteInfo = YogaKitSample;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
13687D771DF878A000E7C260 /* yoga */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = include/yoga;
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
);
|
||||
name = yoga;
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13687D7B1DF878CE00E7C260 /* YogaKit */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = include/YogaKit;
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
);
|
||||
name = YogaKit;
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
13687D431DF8748400E7C260 /* YogaKitSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YogaKitSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13687D521DF8748400E7C260 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
13687D571DF8748400E7C260 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
13687D841DF87D1E00E7C260 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
13687D861DF87D2400E7C260 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
1D2FF4D5FCA6A8C54A4074A3 /* Pods-YogaKitSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-YogaKitSample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-YogaKitSample/Pods-YogaKitSample.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
40BD9F451E477A09002790A9 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
40BD9F4A1E47850C002790A9 /* BasicViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BasicViewController.swift; path = ViewControllers/BasicViewController.swift; sourceTree = "<group>"; };
|
||||
40BD9F4F1E479079002790A9 /* SingleLabelCollectionCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SingleLabelCollectionCell.swift; path = Views/SingleLabelCollectionCell.swift; sourceTree = "<group>"; };
|
||||
40BD9F511E479173002790A9 /* LayoutInclusionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LayoutInclusionViewController.swift; path = ViewControllers/LayoutInclusionViewController.swift; sourceTree = "<group>"; };
|
||||
638A94471E1F06D100A726AD /* ExamplesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExamplesViewController.swift; sourceTree = "<group>"; };
|
||||
638A944F1E215CC800A726AD /* YogaKitSampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = YogaKitSampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
82F0896A88112E957EF37C7F /* Pods-YogaKitSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-YogaKitSample.release.xcconfig"; path = "Pods/Target Support Files/Pods-YogaKitSample/Pods-YogaKitSample.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C80A931E90C7F3088CB86822 /* Pods_YogaKitSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_YogaKitSample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
13687D401DF8748300E7C260 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13687D871DF87D2400E7C260 /* Foundation.framework in Frameworks */,
|
||||
13687D851DF87D1E00E7C260 /* UIKit.framework in Frameworks */,
|
||||
15A7CB5995C9DAB1C8803834 /* Pods_YogaKitSample.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
638A944C1E215CC800A726AD /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
13687D3A1DF8748300E7C260 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13687D451DF8748400E7C260 /* YogaKitSample */,
|
||||
13687D441DF8748400E7C260 /* Products */,
|
||||
13687D831DF87D1E00E7C260 /* Frameworks */,
|
||||
E1C759E3C8E84821213ECE8D /* Pods */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13687D441DF8748400E7C260 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13687D431DF8748400E7C260 /* YogaKitSample.app */,
|
||||
638A944F1E215CC800A726AD /* YogaKitSampleTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13687D451DF8748400E7C260 /* YogaKitSample */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
40BD9F4E1E47902F002790A9 /* Views */,
|
||||
40BD9F481E4784B3002790A9 /* ViewControllers */,
|
||||
638A94471E1F06D100A726AD /* ExamplesViewController.swift */,
|
||||
13687D521DF8748400E7C260 /* Assets.xcassets */,
|
||||
13687D571DF8748400E7C260 /* Info.plist */,
|
||||
40BD9F451E477A09002790A9 /* AppDelegate.swift */,
|
||||
);
|
||||
path = YogaKitSample;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13687D831DF87D1E00E7C260 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13687D861DF87D2400E7C260 /* Foundation.framework */,
|
||||
13687D841DF87D1E00E7C260 /* UIKit.framework */,
|
||||
C80A931E90C7F3088CB86822 /* Pods_YogaKitSample.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
40BD9F481E4784B3002790A9 /* ViewControllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
40BD9F4A1E47850C002790A9 /* BasicViewController.swift */,
|
||||
40BD9F511E479173002790A9 /* LayoutInclusionViewController.swift */,
|
||||
);
|
||||
name = ViewControllers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
40BD9F4E1E47902F002790A9 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
40BD9F4F1E479079002790A9 /* SingleLabelCollectionCell.swift */,
|
||||
);
|
||||
name = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E1C759E3C8E84821213ECE8D /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1D2FF4D5FCA6A8C54A4074A3 /* Pods-YogaKitSample.debug.xcconfig */,
|
||||
82F0896A88112E957EF37C7F /* Pods-YogaKitSample.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
13687D421DF8748300E7C260 /* YogaKitSample */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13687D5A1DF8748400E7C260 /* Build configuration list for PBXNativeTarget "YogaKitSample" */;
|
||||
buildPhases = (
|
||||
513B543F92B2E4F4D1EE1CE7 /* [CP] Check Pods Manifest.lock */,
|
||||
13687D771DF878A000E7C260 /* yoga */,
|
||||
13687D7B1DF878CE00E7C260 /* YogaKit */,
|
||||
13687D3F1DF8748300E7C260 /* Sources */,
|
||||
13687D401DF8748300E7C260 /* Frameworks */,
|
||||
13687D411DF8748300E7C260 /* Resources */,
|
||||
FA2FB9DD6471BDD3FBCE503B /* [CP] Embed Pods Frameworks */,
|
||||
6E01EB987F1564F3D71EBE5A /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = YogaKitSample;
|
||||
productName = YogaKitSample;
|
||||
productReference = 13687D431DF8748400E7C260 /* YogaKitSample.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
638A944E1E215CC800A726AD /* YogaKitSampleTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 638A94561E215CC800A726AD /* Build configuration list for PBXNativeTarget "YogaKitSampleTests" */;
|
||||
buildPhases = (
|
||||
638A944B1E215CC800A726AD /* Sources */,
|
||||
638A944C1E215CC800A726AD /* Frameworks */,
|
||||
638A944D1E215CC800A726AD /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
638A94551E215CC800A726AD /* PBXTargetDependency */,
|
||||
);
|
||||
name = YogaKitSampleTests;
|
||||
productName = YogaKitSampleTests;
|
||||
productReference = 638A944F1E215CC800A726AD /* YogaKitSampleTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
13687D3B1DF8748300E7C260 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0820;
|
||||
ORGANIZATIONNAME = facebook;
|
||||
TargetAttributes = {
|
||||
13687D421DF8748300E7C260 = {
|
||||
CreatedOnToolsVersion = 8.1;
|
||||
LastSwiftMigration = 0820;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
638A944E1E215CC800A726AD = {
|
||||
CreatedOnToolsVersion = 8.2.1;
|
||||
ProvisioningStyle = Automatic;
|
||||
TestTargetID = 13687D421DF8748300E7C260;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 13687D3E1DF8748300E7C260 /* Build configuration list for PBXProject "YogaKitSample" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 13687D3A1DF8748300E7C260;
|
||||
productRefGroup = 13687D441DF8748400E7C260 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13687D421DF8748300E7C260 /* YogaKitSample */,
|
||||
638A944E1E215CC800A726AD /* YogaKitSampleTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
13687D411DF8748300E7C260 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13687D531DF8748400E7C260 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
638A944D1E215CC800A726AD /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
513B543F92B2E4F4D1EE1CE7 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
6E01EB987F1564F3D71EBE5A /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-YogaKitSample/Pods-YogaKitSample-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FA2FB9DD6471BDD3FBCE503B /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-YogaKitSample/Pods-YogaKitSample-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
13687D3F1DF8748300E7C260 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
40BD9F501E479079002790A9 /* SingleLabelCollectionCell.swift in Sources */,
|
||||
40BD9F521E479173002790A9 /* LayoutInclusionViewController.swift in Sources */,
|
||||
638A94481E1F06D100A726AD /* ExamplesViewController.swift in Sources */,
|
||||
40BD9F4B1E47850C002790A9 /* BasicViewController.swift in Sources */,
|
||||
40BD9F461E477A09002790A9 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
638A944B1E215CC800A726AD /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
638A94551E215CC800A726AD /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 13687D421DF8748300E7C260 /* YogaKitSample */;
|
||||
targetProxy = 638A94541E215CC800A726AD /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
13687D581DF8748400E7C260 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.1;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13687D591DF8748400E7C260 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.1;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
13687D5B1DF8748400E7C260 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 1D2FF4D5FCA6A8C54A4074A3 /* Pods-YogaKitSample.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
INFOPLIST_FILE = YogaKitSample/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_INSTALL_OBJC_HEADER = NO;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13687D5C1DF8748400E7C260 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 82F0896A88112E957EF37C7F /* Pods-YogaKitSample.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
INFOPLIST_FILE = YogaKitSample/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_INSTALL_OBJC_HEADER = NO;
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
638A94571E215CC800A726AD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
INFOPLIST_FILE = YogaKitSampleTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSampleTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/YogaKitSample.app/YogaKitSample";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
638A94581E215CC800A726AD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
INFOPLIST_FILE = YogaKitSampleTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSampleTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/YogaKitSample.app/YogaKitSample";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
13687D3E1DF8748300E7C260 /* Build configuration list for PBXProject "YogaKitSample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13687D581DF8748400E7C260 /* Debug */,
|
||||
13687D591DF8748400E7C260 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
13687D5A1DF8748400E7C260 /* Build configuration list for PBXNativeTarget "YogaKitSample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13687D5B1DF8748400E7C260 /* Debug */,
|
||||
13687D5C1DF8748400E7C260 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
638A94561E215CC800A726AD /* Build configuration list for PBXNativeTarget "YogaKitSampleTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
638A94571E215CC800A726AD /* Debug */,
|
||||
638A94581E215CC800A726AD /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 13687D3B1DF8748300E7C260 /* Project object */;
|
||||
}
|
7
YogaKit/YogaKitSample/YogaKitSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:YogaKitSample.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
10
YogaKit/YogaKitSample/YogaKitSample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:YogaKitSample.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
27
YogaKit/YogaKitSample/YogaKitSample/AppDelegate.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE-examples file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
var window: UIWindow?
|
||||
|
||||
func applicationDidFinishLaunching(_ application: UIApplication) {
|
||||
self.window = UIWindow(frame: UIScreen.main.bounds)
|
||||
if let window = self.window {
|
||||
let navigationController = UINavigationController(rootViewController: ExamplesViewController())
|
||||
navigationController.navigationBar.isTranslucent = false
|
||||
|
||||
window.rootViewController = navigationController
|
||||
window.backgroundColor = .white
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-20x20@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-29x29@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-40x40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "57x57",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-57x57@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "57x57",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-57x57@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-60x60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Yoga-60x60@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 868 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 7.4 KiB |
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
100
YogaKit/YogaKitSample/YogaKitSample/ExamplesViewController.swift
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE-examples file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
import IGListKit
|
||||
|
||||
private final class ExampleModel {
|
||||
let title: String
|
||||
let controllerClass: UIViewController.Type
|
||||
|
||||
init(title: String, controllerClass: UIViewController.Type) {
|
||||
self.title = title
|
||||
self.controllerClass = controllerClass
|
||||
}
|
||||
}
|
||||
|
||||
extension ExampleModel: IGListDiffable {
|
||||
fileprivate func diffIdentifier() -> NSObjectProtocol {
|
||||
return title as NSString
|
||||
}
|
||||
|
||||
fileprivate func isEqual(toDiffableObject object: IGListDiffable?) -> Bool {
|
||||
guard let otherObj = object as? ExampleModel else { return false }
|
||||
|
||||
return (title == otherObj.title) &&
|
||||
(controllerClass == otherObj.controllerClass)
|
||||
}
|
||||
}
|
||||
|
||||
final class ExamplesViewController: UIViewController, IGListAdapterDataSource, IGListSingleSectionControllerDelegate {
|
||||
private lazy var adapter: IGListAdapter = {
|
||||
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
|
||||
}()
|
||||
private let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
|
||||
|
||||
|
||||
// Update this to array to create more examples.
|
||||
private let models: [ExampleModel] = [ExampleModel(title: "Basic Layout", controllerClass: BasicViewController.self),
|
||||
ExampleModel(title: "Exclude Views in Layout", controllerClass: LayoutInclusionViewController.self)]
|
||||
|
||||
//MARK: UIViewController
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
title = "Examples"
|
||||
view.addSubview(collectionView)
|
||||
adapter.collectionView = collectionView
|
||||
adapter.dataSource = self
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
collectionView.frame = view.bounds
|
||||
}
|
||||
|
||||
//MARK: IGListAdapterDataSource
|
||||
|
||||
func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
|
||||
return models as [IGListDiffable]
|
||||
}
|
||||
|
||||
func listAdapter(_ listAdapter: IGListAdapter, sectionControllerFor object: Any) -> IGListSectionController {
|
||||
let sizeBlock: IGListSingleSectionCellSizeBlock = { (model, context) in
|
||||
return CGSize(width: (context?.containerSize.width)!, height: 75.0)
|
||||
}
|
||||
|
||||
let configureBlock: IGListSingleSectionCellConfigureBlock = { (model, cell) in
|
||||
guard let m = model as? ExampleModel, let c = cell as? SingleLabelCollectionCell else {
|
||||
return
|
||||
}
|
||||
|
||||
c.label.text = m.title
|
||||
}
|
||||
|
||||
let sectionController = IGListSingleSectionController(cellClass: SingleLabelCollectionCell.self,
|
||||
configureBlock: configureBlock,
|
||||
sizeBlock: sizeBlock)
|
||||
sectionController.selectionDelegate = self
|
||||
return sectionController
|
||||
}
|
||||
|
||||
func emptyView(for listAdapter: IGListAdapter) -> UIView? { return nil }
|
||||
|
||||
//MARK: IGListSingleSectionControllerDelegate
|
||||
|
||||
func didSelect(_ sectionController: IGListSingleSectionController) {
|
||||
let section = adapter.section(for: sectionController)
|
||||
let model = models[section]
|
||||
|
||||
let controller = model.controllerClass.init()
|
||||
controller.title = model.title
|
||||
|
||||
self.navigationController?.pushViewController(controller, animated: true)
|
||||
}
|
||||
}
|
36
YogaKit/YogaKitSample/YogaKitSample/Info.plist
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string></string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE-examples file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
import IGListKit
|
||||
import YogaKit
|
||||
|
||||
struct DemoItem {
|
||||
let name: String
|
||||
}
|
||||
|
||||
final class SwiftViewController: UIViewController, IGListAdapterDataSource {
|
||||
|
||||
lazy var adapter: IGListAdapter = {
|
||||
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
|
||||
}()
|
||||
let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
|
||||
|
||||
//MARK: UIViewController
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
title = "YogaKit Examples"
|
||||
view.addSubview(collectionView)
|
||||
adapter.collectionView = collectionView
|
||||
adapter.dataSource = self
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
collectionView.frame = view.bounds
|
||||
}
|
||||
|
||||
|
||||
//MARK: IGListAdapterDataSource
|
||||
|
||||
func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
|
||||
return ["Dustin" as IGListDiffable, "Ryan" as IGListDiffable]
|
||||
}
|
||||
|
||||
func listAdapter(_ listAdapter: IGListAdapter, sectionControllerFor object: Any) -> IGListSectionController {
|
||||
let sizeBlock: IGListSingleSectionCellSizeBlock = { (model, context) in
|
||||
return CGSize(width: (context?.containerSize.width)!, height: 100.0)
|
||||
}
|
||||
let configureBlock: IGListSingleSectionCellConfigureBlock = { (model, cell) in
|
||||
guard let m = model as? String else {
|
||||
return
|
||||
}
|
||||
|
||||
cell.backgroundColor = (m == "Dustin") ? .blue : .red
|
||||
}
|
||||
|
||||
return IGListSingleSectionController(cellClass: UICollectionViewCell.self,
|
||||
configureBlock: configureBlock,
|
||||
sizeBlock: sizeBlock)
|
||||
}
|
||||
|
||||
func emptyView(for listAdapter: IGListAdapter) -> UIView? {
|
||||
return nil
|
||||
}
|
||||
}
|
56
YogaKit/YogaKitSample/YogaKitSample/ViewController.m
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE-examples file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "ViewController.h"
|
||||
|
||||
#import <YogaKit/UIView+Yoga.h>
|
||||
|
||||
@implementation ViewController
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
UIView *root = self.view;
|
||||
root.backgroundColor = [UIColor redColor];
|
||||
root.yoga.isEnabled = YES;
|
||||
root.yoga.width = self.view.bounds.size.width;
|
||||
root.yoga.height = self.view.bounds.size.height;
|
||||
root.yoga.alignItems = YGAlignCenter;
|
||||
root.yoga.justifyContent = YGJustifyCenter;
|
||||
|
||||
UIView *child1 = [UIView new];
|
||||
child1.backgroundColor = [UIColor blueColor];
|
||||
child1.yoga.isEnabled = YES;
|
||||
child1.yoga.width = 100;
|
||||
child1.yoga.height = 100;
|
||||
|
||||
UIView *child2 = [UIView new];
|
||||
child2.backgroundColor = [UIColor greenColor];
|
||||
child2.frame = (CGRect) {
|
||||
.size = {
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
}
|
||||
};
|
||||
|
||||
UIView *child3 = [UIView new];
|
||||
child3.backgroundColor = [UIColor yellowColor];
|
||||
child3.frame = (CGRect) {
|
||||
.size = {
|
||||
.width = 100,
|
||||
.height = 100,
|
||||
}
|
||||
};
|
||||
|
||||
[child2 addSubview:child3];
|
||||
[root addSubview:child1];
|
||||
[root addSubview:child2];
|
||||
[root.yoga applyLayoutPreservingOrigin:NO];
|
||||
}
|
||||
|
||||
|
||||
@end
|
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE-examples file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
import YogaKit
|
||||
|
||||
final class BasicViewController: UIViewController {
|
||||
override func viewDidLoad() {
|
||||
let containerSize = self.view.bounds.size
|
||||
|
||||
let root = self.view!
|
||||
root.backgroundColor = .white
|
||||
root.yoga.isEnabled = true
|
||||
root.yoga.width = containerSize.width
|
||||
root.yoga.height = containerSize.height
|
||||
root.yoga.alignItems = .center
|
||||
root.yoga.justifyContent = .center
|
||||
|
||||
let child1 = UIView()
|
||||
child1.backgroundColor = .blue
|
||||
child1.yoga.isEnabled = true
|
||||
child1.yoga.width = 100
|
||||
child1.yoga.height = 10
|
||||
child1.yoga.marginBottom = 25
|
||||
root.addSubview(child1)
|
||||
|
||||
let child2 = UIView()
|
||||
child2.yoga.isEnabled = true
|
||||
child2.yoga.alignSelf = .flexEnd
|
||||
child2.backgroundColor = .green
|
||||
child2.frame = CGRect(x: 0, y: 0, width: 200, height: 100)
|
||||
root.addSubview(child2)
|
||||
|
||||
let child3 = UIView()
|
||||
child3.yoga.isEnabled = true
|
||||
child3.yoga.alignSelf = .flexStart
|
||||
child3.backgroundColor = .yellow
|
||||
child3.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
|
||||
root.addSubview(child3)
|
||||
|
||||
root.yoga.applyLayout(preservingOrigin: true)
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE-examples file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
import YogaKit
|
||||
|
||||
final class LayoutInclusionViewController: UIViewController {
|
||||
private let button: UIButton = UIButton(type: .system)
|
||||
private let disappearingView: UIView = UIView(frame: .zero)
|
||||
private let contentView: UIView = UIView(frame: .zero)
|
||||
|
||||
override func viewDidLoad() {
|
||||
let root = self.view!
|
||||
root.backgroundColor = .white
|
||||
root.yoga.isEnabled = true
|
||||
root.yoga.flexDirection = .column
|
||||
root.yoga.justifyContent = .spaceAround
|
||||
|
||||
contentView.backgroundColor = .clear
|
||||
contentView.layer.borderColor = UIColor.lightGray.cgColor
|
||||
contentView.layer.borderWidth = 1.0
|
||||
contentView.yoga.isEnabled = true
|
||||
contentView.yoga.height = 300
|
||||
contentView.yoga.width = self.view.bounds.size.width
|
||||
contentView.yoga.flexDirection = .row
|
||||
contentView.yoga.justifyContent = .center
|
||||
contentView.yoga.paddingHorizontal = 25
|
||||
self.view.addSubview(contentView)
|
||||
|
||||
let redView = UIView(frame: .zero)
|
||||
redView.backgroundColor = .red
|
||||
redView.yoga.isEnabled = true
|
||||
redView.yoga.flexGrow = 1
|
||||
redView.yoga.flexShrink = 1
|
||||
contentView.addSubview(redView)
|
||||
|
||||
disappearingView.backgroundColor = .blue
|
||||
disappearingView.yoga.isEnabled = true
|
||||
disappearingView.yoga.flexGrow = 1
|
||||
contentView.addSubview(disappearingView)
|
||||
|
||||
button.setTitle("Add Blue View", for: UIControlState.selected)
|
||||
button.setTitle("Remove Blue View", for: UIControlState.normal)
|
||||
button.addTarget(self, action: #selector(buttonWasTapped), for: UIControlEvents.touchUpInside)
|
||||
button.yoga.isEnabled = true
|
||||
button.yoga.height = 300
|
||||
button.yoga.width = 300
|
||||
button.yoga.alignSelf = .center
|
||||
root.addSubview(button)
|
||||
|
||||
root.yoga.applyLayout(preservingOrigin: false)
|
||||
}
|
||||
|
||||
// MARK - UIButton Action
|
||||
func buttonWasTapped() {
|
||||
button.isSelected = !button.isSelected
|
||||
|
||||
button.isUserInteractionEnabled = false
|
||||
disappearingView.yoga.isIncludedInLayout = !disappearingView.yoga.isIncludedInLayout
|
||||
disappearingView.isHidden = !disappearingView.isHidden
|
||||
|
||||
contentView.yoga.applyLayout(preservingOrigin: true)
|
||||
button.isUserInteractionEnabled = true
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE-examples file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
import YogaKit
|
||||
|
||||
final class SingleLabelCollectionCell: UICollectionViewCell {
|
||||
let label: UILabel = UILabel(frame: .zero)
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
contentView.yoga.isEnabled = true
|
||||
contentView.yoga.flexDirection = .column
|
||||
contentView.yoga.justifyContent = .flexEnd
|
||||
|
||||
label.textAlignment = .center
|
||||
label.numberOfLines = 1
|
||||
label.yoga.isIncludedInLayout = false
|
||||
contentView.addSubview(label)
|
||||
|
||||
let border = UIView(frame: .zero)
|
||||
border.backgroundColor = .lightGray
|
||||
border.yoga.isEnabled = true
|
||||
border.yoga.height = 0.5
|
||||
border.yoga.marginHorizontal = 25
|
||||
contentView.addSubview(border)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
contentView.yoga.applyLayout(preservingOrigin: false)
|
||||
label.frame = contentView.bounds
|
||||
}
|
||||
}
|
36
android/BUCK
Normal file
@@ -0,0 +1,36 @@
|
||||
# Copyright (c) 2014-present, Facebook, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under the BSD-style license found in the
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
include_defs('//YOGA_DEFS')
|
||||
|
||||
android_aar(
|
||||
name = 'android',
|
||||
manifest_skeleton = 'src/main/AndroidManifest.xml',
|
||||
deps = [
|
||||
ANDROID_JAVA_TARGET,
|
||||
ANDROID_RES_TARGET,
|
||||
INFER_ANNOTATIONS_TARGET,
|
||||
JAVA_TARGET,
|
||||
PROGRUARD_ANNOTATIONS_TARGET,
|
||||
],
|
||||
visibility = [
|
||||
'PUBLIC',
|
||||
],
|
||||
)
|
||||
|
||||
android_resource(
|
||||
name = 'res',
|
||||
res = 'src/main/res',
|
||||
package = 'com.facebook.yoga.android',
|
||||
visibility = [
|
||||
'PUBLIC',
|
||||
],
|
||||
)
|
||||
|
||||
project_config(
|
||||
src_target = ':android',
|
||||
)
|
59
android/build.gradle
Normal file
@@ -0,0 +1,59 @@
|
||||
apply plugin: "com.jfrog.bintray"
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'com.github.dcendents.android-maven'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
targetCompatibility = '1.7'
|
||||
sourceCompatibility = '1.7'
|
||||
|
||||
version = '1.0.0'
|
||||
group = 'com.facebook.yoga.android'
|
||||
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion "19.1.0"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 19
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
|
||||
sourceSets.main {
|
||||
jni.srcDirs = [] // disalbe NDK auto build (not sure why this is necessary)
|
||||
// The alternative, fat-aar does an equivalent thing to this hack
|
||||
// seehttps://github.com/adwiv/android-fat-aar/blob/master/fat-aar.gradle#L307
|
||||
jniLibs.srcDirs = ['build/intermediates/exploded-aar/com.facebook.yoga/yoga/1.0.0/jni']
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':yoga')
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
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.android:yoga-layout"
|
||||
}
|
||||
|
||||
apply from: rootProject.file('gradle/android-jcenter-install.gradle')
|
46
android/sample/AndroidManifest.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the license found in the
|
||||
LICENSE-examples file in the root directory of this source tree.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.facebook.samples.yoga"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
>
|
||||
|
||||
<variable name="applicationId" value="com.facebook.yoga"/>
|
||||
<variable name="app_label" value="Yoga Sample App"/>
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="15"
|
||||
android:targetSdkVersion="19"
|
||||
/>
|
||||
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:allowBackup="false"
|
||||
android:theme="@style/NoTitleBarWhiteBG"
|
||||
>
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
39
android/sample/BUCK
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright 2014-present, Facebook, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under the license found in the
|
||||
# LICENSE-examples file in the root directory of this source tree.
|
||||
|
||||
include_defs('//YOGA_DEFS')
|
||||
|
||||
android_binary(
|
||||
name = 'sample',
|
||||
manifest = 'AndroidManifest.xml',
|
||||
keystore = ':debug_keystore',
|
||||
deps = [
|
||||
ANDROID_SAMPLE_JAVA_TARGET,
|
||||
ANDROID_SAMPLE_RES_TARGET,
|
||||
],
|
||||
)
|
||||
|
||||
android_resource(
|
||||
name = 'res',
|
||||
res = 'res',
|
||||
package = 'com.facebook.samples.yoga',
|
||||
deps = [
|
||||
ANDROID_RES_TARGET,
|
||||
],
|
||||
visibility = [
|
||||
'PUBLIC',
|
||||
],
|
||||
)
|
||||
|
||||
keystore(
|
||||
name='debug_keystore',
|
||||
store='debug.keystore',
|
||||
properties='debug.keystore.properties',
|
||||
)
|
||||
|
||||
project_config(
|
||||
src_target = ':sample',
|
||||
)
|
BIN
android/sample/debug.keystore
Normal file
3
android/sample/debug.keystore.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
key.alias=androiddebugkey
|
||||
key.store.password=android
|
||||
key.alias.password=android
|
23
android/sample/java/com/facebook/samples/yoga/BUCK
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2014-present, Facebook, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under the BSD-style license found in the
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
include_defs('//YOGA_DEFS')
|
||||
|
||||
android_library(
|
||||
name = 'yoga',
|
||||
srcs = glob(['**/*.java']),
|
||||
deps = [
|
||||
ANDROID_JAVA_TARGET,
|
||||
ANDROID_SAMPLE_RES_TARGET,
|
||||
ANDROID_SUPPORT_TARGET,
|
||||
APPCOMPAT_TARGET,
|
||||
SOLOADER_TARGET,
|
||||
],
|
||||
visibility = [
|
||||
'PUBLIC',
|
||||
]
|
||||
)
|
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE-examples file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.samples.yoga;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import com.facebook.samples.yoga.R;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import com.facebook.yoga.android.YogaViewLayoutFactory;
|
||||
|
||||
/**
|
||||
* An activity to show off Yoga in Android. This activity shows a simple layout (defined in
|
||||
* {@code main_layout.xml}) that shows off the awesome functionality of the Yoga layout engine
|
||||
* as well as some optimisations on layout systems that it facilitates.
|
||||
*/
|
||||
public class MainActivity extends ActionBarActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
LayoutInflater.from(this).setFactory(YogaViewLayoutFactory.getInstance());
|
||||
super.onCreate(savedInstanceState);
|
||||
SoLoader.init(this, false);
|
||||
|
||||
setContentView(R.layout.main_layout);
|
||||
}
|
||||
}
|
17
android/sample/res/drawable/action_bar_background.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<!--
|
||||
Copyright 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the license found in the
|
||||
LICENSE-examples file in the root directory of this source tree.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle"
|
||||
>
|
||||
<solid
|
||||
android:color="@color/yoga_grey"
|
||||
/>
|
||||
</shape>
|
BIN
android/sample/res/drawable/ic_launcher.png
Normal file
After Width: | Height: | Size: 28 KiB |
34
android/sample/res/drawable/sample_children_background.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<!--
|
||||
Copyright 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the license found in the
|
||||
LICENSE-examples file in the root directory of this source tree.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle"
|
||||
>
|
||||
|
||||
<corners
|
||||
android:radius="4dp"
|
||||
/>
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/children_stroke"
|
||||
/>
|
||||
|
||||
<padding
|
||||
android:top="6dp"
|
||||
android:bottom="6dp"
|
||||
android:left="8dp"
|
||||
android:right="8dp"
|
||||
/>
|
||||
|
||||
<solid
|
||||
android:color="@color/children_background"
|
||||
/>
|
||||
</shape>
|
137
android/sample/res/layout/main_layout.xml
Normal file
@@ -0,0 +1,137 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<!--
|
||||
Copyright 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the license found in the
|
||||
LICENSE-examples file in the root directory of this source tree.
|
||||
-->
|
||||
|
||||
<YogaLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:yoga="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
>
|
||||
<YogaLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/sample_children_background"
|
||||
yoga:margin_horizontal="10dp"
|
||||
yoga:margin_top="5dp"
|
||||
yoga:flex_direction="row"
|
||||
yoga:align_items="center"
|
||||
>
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:src="@drawable/ic_launcher"
|
||||
yoga:flex="0"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/child_1_text"
|
||||
android:textColor="@color/children_text"
|
||||
yoga:flex="1"
|
||||
yoga:margin_start="8dp"
|
||||
/>
|
||||
</YogaLayout>
|
||||
<YogaLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/sample_children_background"
|
||||
yoga:margin_horizontal="10dp"
|
||||
yoga:margin_top="5dp"
|
||||
yoga:flex_direction="row"
|
||||
yoga:align_items="center"
|
||||
>
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:src="@drawable/ic_launcher"
|
||||
yoga:flex="0"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/child_2_text"
|
||||
android:textColor="@color/children_text"
|
||||
yoga:flex="1"
|
||||
yoga:margin_start="8dp"
|
||||
/>
|
||||
</YogaLayout>
|
||||
<YogaLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/sample_children_background"
|
||||
yoga:margin_horizontal="10dp"
|
||||
yoga:margin_top="5dp"
|
||||
yoga:flex_direction="row"
|
||||
yoga:align_items="center"
|
||||
>
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:src="@drawable/ic_launcher"
|
||||
yoga:flex="0"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/child_3_text"
|
||||
android:textColor="@color/children_text"
|
||||
yoga:flex="1"
|
||||
yoga:margin_start="8dp"
|
||||
/>
|
||||
</YogaLayout>
|
||||
<YogaLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/sample_children_background"
|
||||
yoga:margin_horizontal="10dp"
|
||||
yoga:margin_top="5dp"
|
||||
yoga:flex_direction="row"
|
||||
yoga:align_items="center"
|
||||
>
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:src="@drawable/ic_launcher"
|
||||
yoga:flex="0"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/child_4_text"
|
||||
android:textColor="@color/children_text"
|
||||
yoga:flex="1"
|
||||
yoga:margin_start="8dp"
|
||||
/>
|
||||
</YogaLayout>
|
||||
<YogaLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/sample_children_background"
|
||||
yoga:margin_horizontal="10dp"
|
||||
yoga:margin_top="5dp"
|
||||
yoga:flex_direction="row"
|
||||
yoga:align_items="center"
|
||||
>
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:src="@drawable/ic_launcher"
|
||||
yoga:flex="0"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/child_5_text"
|
||||
android:textColor="@color/children_text"
|
||||
yoga:flex="1"
|
||||
yoga:margin_start="10dp"
|
||||
/>
|
||||
</YogaLayout>
|
||||
</YogaLayout>
|
20
android/sample/res/values/colors.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the license found in the
|
||||
LICENSE-examples file in the root directory of this source tree.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<color name="yoga_grey">#FF303846</color>
|
||||
<color name="yoga_blue">#FF97DCCF</color>
|
||||
|
||||
<color name="children_background">#FFFFFFFF</color>
|
||||
<color name="children_stroke">#665890ff</color>
|
||||
<color name="children_text">#FF23355b</color>
|
||||
|
||||
</resources>
|
33
android/sample/res/values/strings.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the license found in the
|
||||
LICENSE-examples file in the root directory of this source tree.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<string name="app_name">Yoga</string>
|
||||
<string
|
||||
name="child_1_text"
|
||||
description="Placeholder text for the first element in the layout"
|
||||
>Hello. I am Yoga!</string>
|
||||
<string
|
||||
name="child_2_text"
|
||||
description="Placeholder text for the second element in the layout"
|
||||
>I am a layout engine!</string>
|
||||
<string
|
||||
name="child_3_text"
|
||||
description="Placeholder text for the third element in the layout"
|
||||
>I run natively.</string>
|
||||
<string
|
||||
name="child_4_text"
|
||||
description="Placeholder text for the fourth element in the layout"
|
||||
>So I\'m fast.</string>
|
||||
<string
|
||||
name="child_5_text"
|
||||
description="Placeholder text for the fifth element in the layout"
|
||||
>Who are you?</string>
|
||||
</resources>
|
23
android/sample/res/values/styles.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the license found in the
|
||||
LICENSE-examples file in the root directory of this source tree.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<style name="NoTitleBarWhiteBG" parent="Theme.AppCompat.Light">
|
||||
<item name="android:actionBarStyle">@style/MyActionBar</item>
|
||||
<item name="android:textDirection">locale</item>
|
||||
</style>
|
||||
<style name="MyActionBar" parent="Widget.AppCompat.Light.ActionBar">
|
||||
<item name="android:titleTextStyle">@style/MyTitleText</item>
|
||||
<item name="android:background">@drawable/action_bar_background</item>
|
||||
</style>
|
||||
<style name="MyTitleText" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
|
||||
<item name="android:textColor">@color/yoga_blue</item>
|
||||
</style>
|
||||
</resources>
|
25
android/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the BSD-style license found in the
|
||||
LICENSE file in the root directory of this source tree. An additional grant
|
||||
of patent rights can be found in the PATENTS file in the same directory.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.facebook.yoga.android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
>
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="15"
|
||||
android:targetSdkVersion="19"
|
||||
/>
|
||||
|
||||
<application/>
|
||||
|
||||
</manifest>
|
23
android/src/main/java/com/facebook/yoga/android/BUCK
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2014-present, Facebook, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under the BSD-style license found in the
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
include_defs('//YOGA_DEFS')
|
||||
|
||||
android_library(
|
||||
name = 'android',
|
||||
srcs = glob(['**/*.java']),
|
||||
deps = [
|
||||
ANDROID_RES_TARGET,
|
||||
INFER_ANNOTATIONS_TARGET,
|
||||
JAVA_TARGET,
|
||||
JSR_305_TARGET,
|
||||
SOLOADER_TARGET,
|
||||
],
|
||||
visibility = [
|
||||
'PUBLIC',
|
||||
]
|
||||
)
|
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.yoga.android;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.facebook.yoga.YogaNode;
|
||||
|
||||
/**
|
||||
* Much like a {@link YogaLayout}, except this class does not render itself (the container) to the
|
||||
* screen. As a result, <i>do not use this if you wish the container to have a background or
|
||||
* foreground</i>. However, all of its children will still render as expected.
|
||||
*
|
||||
* <p>
|
||||
* In practice, this class never added to the View tree, and all its children become children of its
|
||||
* parent. As a result, all the layout (such as the traversal of the tree) is performed by Yoga
|
||||
* (and so natively) increasing performance.
|
||||
*/
|
||||
public class VirtualYogaLayout extends ViewGroup {
|
||||
|
||||
final private List<View> mChildren = new LinkedList<>();
|
||||
final private Map<View, YogaNode> mYogaNodes = new HashMap<>();
|
||||
final private YogaNode mYogaNode = new YogaNode();
|
||||
|
||||
public VirtualYogaLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public VirtualYogaLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public VirtualYogaLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
YogaLayout.LayoutParams lp = new YogaLayout.LayoutParams(context, attrs);
|
||||
YogaLayout.applyLayoutParams(lp, mYogaNode, this);
|
||||
}
|
||||
|
||||
public YogaNode getYogaNode() {
|
||||
return mYogaNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to add a view, creating a new yoga node for it and adding that yoga node to the parent.
|
||||
* If the child is a {@link VirtualYogaLayout}, we simply transfer all its children to this one
|
||||
* in a manner that maintains the tree, and add its root to the tree.
|
||||
*
|
||||
* @param child the View to add
|
||||
* @param index the position at which to add it (ignored)
|
||||
* @param params the layout parameters to apply
|
||||
*/
|
||||
@Override
|
||||
public void addView(View child, int index, ViewGroup.LayoutParams params) {
|
||||
if (child instanceof VirtualYogaLayout) {
|
||||
((VirtualYogaLayout) child).transferChildren(this);
|
||||
|
||||
final YogaNode childNode = ((VirtualYogaLayout) child).getYogaNode();
|
||||
mYogaNode.addChildAt(childNode, mYogaNode.getChildCount());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
YogaNode node = new YogaNode();
|
||||
YogaLayout.LayoutParams lp = new YogaLayout.LayoutParams(params);
|
||||
YogaLayout.applyLayoutParams(lp, node, child);
|
||||
node.setData(child);
|
||||
node.setMeasureFunction(new YogaLayout.ViewMeasureFunction());
|
||||
|
||||
mYogaNode.addChildAt(node, mYogaNode.getChildCount());
|
||||
|
||||
addView(child, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to add a view with a corresponding node, but not to change the Yoga tree in any way.
|
||||
*
|
||||
* @param child the View to add
|
||||
* @param node the corresponding yoga node
|
||||
*/
|
||||
public void addView(View child, YogaNode node) {
|
||||
mChildren.add(child);
|
||||
mYogaNodes.put(child, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives up children {@code View}s to the parent, maintaining the Yoga tree. This function calls
|
||||
* {@link YogaLayout#addView(View, YogaNode)} or {@link VirtualYogaLayout#addView(View, YogaNode)}
|
||||
* on the parent to add the {@code View} without generating new yoga nodes.
|
||||
*
|
||||
* @param parent the parent to pass children to (must be a YogaLayout or a VirtualYogaLayout)
|
||||
*/
|
||||
protected void transferChildren(ViewGroup parent) {
|
||||
if (parent instanceof VirtualYogaLayout) {
|
||||
for (View child : mChildren) {
|
||||
((VirtualYogaLayout) parent).addView(child, mYogaNodes.get(child));
|
||||
}
|
||||
} else if (parent instanceof YogaLayout) {
|
||||
for (View child : mChildren) {
|
||||
((YogaLayout) parent).addView(child, mYogaNodes.get(child));
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("VirtualYogaLayout cannot transfer children to ViewGroup of type "
|
||||
+parent.getClass().getCanonicalName()+". Must either be a VirtualYogaLayout or a " +
|
||||
"YogaLayout.");
|
||||
}
|
||||
mChildren.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
throw new RuntimeException("Attempting to layout a VirtualYogaLayout");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
|
||||
return new YogaLayout.LayoutParams(getContext(), attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
|
||||
return new YogaLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
|
||||
return new YogaLayout.LayoutParams(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
|
||||
return p instanceof YogaLayout.LayoutParams;
|
||||
}
|
||||
}
|
746
android/src/main/java/com/facebook/yoga/android/YogaLayout.java
Normal file
@@ -0,0 +1,746 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.yoga.android;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.facebook.yoga.android.R;
|
||||
import com.facebook.yoga.YogaAlign;
|
||||
import com.facebook.yoga.YogaConstants;
|
||||
import com.facebook.yoga.YogaDirection;
|
||||
import com.facebook.yoga.YogaEdge;
|
||||
import com.facebook.yoga.YogaFlexDirection;
|
||||
import com.facebook.yoga.YogaJustify;
|
||||
import com.facebook.yoga.YogaMeasureFunction;
|
||||
import com.facebook.yoga.YogaMeasureMode;
|
||||
import com.facebook.yoga.YogaMeasureOutput;
|
||||
import com.facebook.yoga.YogaNode;
|
||||
import com.facebook.yoga.YogaNodeAPI;
|
||||
import com.facebook.yoga.YogaOverflow;
|
||||
import com.facebook.yoga.YogaPositionType;
|
||||
import com.facebook.yoga.YogaWrap;
|
||||
|
||||
/**
|
||||
* A {@code ViewGroup} based on the Yoga layout engine.
|
||||
*
|
||||
* <p>
|
||||
* This class is designed to be as "plug and play" as possible. That is, you can use it in XML
|
||||
* like this (note: to use {@code YogaLayout} you need to use the {@link YogaViewLayoutFactory}):
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
* <YogaLayout
|
||||
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* xmlns:yoga="http://schemas.android.com/apk/res-auto"
|
||||
* android:layout_width="match_parent"
|
||||
* android:layout_height="match_parent"
|
||||
* yoga:flex_direction="row"
|
||||
* yoga:padding_all="10dp"
|
||||
* >
|
||||
* <TextView
|
||||
* android:layout_width="match_parent"
|
||||
* android:layout_height="match_parent"
|
||||
* android:text="Hello, World!"
|
||||
* yoga:flex="1"
|
||||
* />
|
||||
* </YogaLayout>
|
||||
* }</pre>
|
||||
*
|
||||
* Under the hood, all views added to this {@code ViewGroup} are laid out using flexbox rules
|
||||
* and the Yoga engine.
|
||||
*/
|
||||
public class YogaLayout extends ViewGroup {
|
||||
private final Map<View, YogaNode> mYogaNodes;
|
||||
private final YogaNode mYogaNode;
|
||||
|
||||
public YogaLayout(Context context) {
|
||||
this(context, null, 0);
|
||||
}
|
||||
|
||||
public YogaLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public YogaLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
mYogaNode = new YogaNode();
|
||||
mYogaNodes = new HashMap<>();
|
||||
|
||||
mYogaNode.setData(this);
|
||||
mYogaNode.setMeasureFunction(new ViewMeasureFunction());
|
||||
|
||||
final LayoutParams layoutParams = new LayoutParams(context, attrs);
|
||||
applyLayoutParams(layoutParams, mYogaNode, this);
|
||||
}
|
||||
|
||||
YogaNode getYogaNode() {
|
||||
return mYogaNode;
|
||||
}
|
||||
|
||||
YogaNode getYogaNodeForView(View view) {
|
||||
return mYogaNodes.get(view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a child view with the specified layout parameters.
|
||||
*
|
||||
* In the typical View is added, this constructs a {@code YogaNode} for this child and applies all
|
||||
* the {@code yoga:*} attributes. The Toga node is added to the Yoga tree and the child is added
|
||||
* to this ViewGroup.
|
||||
*
|
||||
* If the child is a {@link YogaLayout} itself, we do not construct a new Yoga node for that
|
||||
* child, but use its root node instead.
|
||||
*
|
||||
* If the child is a {@link VirtualYogaLayout}, we also use its Yoga node, but we also instruct it
|
||||
* to transfer all of its children to this {@link YogaLayout} while preserving the Yoga tree (so
|
||||
* that the layout of its children is correct). The {@link VirtualYogaLayout} is then not added
|
||||
* to the View hierarchy.
|
||||
*
|
||||
* <p><strong>Note:</strong> do not invoke this method from
|
||||
* {@code #draw(android.graphics.Canvas)}, {@code onDraw(android.graphics.Canvas)},
|
||||
* {@code #dispatchDraw(android.graphics.Canvas)} or any related method.</p>
|
||||
*
|
||||
* @param child the child view to add
|
||||
* @param index the position at which to add the child or -1 to add last
|
||||
* @param params the layout parameters to set on the child
|
||||
*/
|
||||
@Override
|
||||
public void addView(View child, int index, ViewGroup.LayoutParams params) {
|
||||
// Internal nodes (which this is now) cannot have measure functions
|
||||
mYogaNode.setMeasureFunction(null);
|
||||
|
||||
if (child instanceof VirtualYogaLayout) {
|
||||
((VirtualYogaLayout) child).transferChildren(this);
|
||||
final YogaNode childNode = ((VirtualYogaLayout) child).getYogaNode();
|
||||
|
||||
mYogaNode.addChildAt(childNode, mYogaNode.getChildCount());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
super.addView(child, index, params);
|
||||
|
||||
// It is possible that addView is being called as part of a transferal of children, in which
|
||||
// case we already know about the YogaNode and only need the Android View tree to be aware
|
||||
// that we now own this child. If so, we don't need to do anything further
|
||||
if (mYogaNodes.containsKey(child)) {
|
||||
return;
|
||||
}
|
||||
|
||||
YogaNode childNode;
|
||||
|
||||
if (child instanceof YogaLayout) {
|
||||
childNode = ((YogaLayout) child).getYogaNode();
|
||||
} else {
|
||||
childNode = new YogaNode();
|
||||
|
||||
childNode.setData(child);
|
||||
childNode.setMeasureFunction(new ViewMeasureFunction());
|
||||
}
|
||||
|
||||
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
applyLayoutParams(lp, childNode, child);
|
||||
|
||||
mYogaNodes.put(child, childNode);
|
||||
mYogaNode.addChildAt(childNode, mYogaNode.getChildCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a view to this {@code ViewGroup} with an already given {@code YogaNode}. Use
|
||||
* this function if you already have a Yoga node (and perhaps tree) associated with the view you
|
||||
* are adding, that you would like to preserve.
|
||||
*
|
||||
* @param child The view to add
|
||||
* @param node The Yoga node belonging to the view
|
||||
*/
|
||||
public void addView(View child, YogaNode node) {
|
||||
mYogaNodes.put(child, node);
|
||||
addView(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeView(View view) {
|
||||
removeViewFromYogaTree(view, false);
|
||||
super.removeView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewAt(int index) {
|
||||
removeViewFromYogaTree(getChildAt(index), false);
|
||||
super.removeViewAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewInLayout(View view) {
|
||||
removeViewFromYogaTree(view, true);
|
||||
super.removeViewInLayout(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViews(int start, int count) {
|
||||
for (int i = start; i < start + count; i++) {
|
||||
removeViewFromYogaTree(getChildAt(i), false);
|
||||
}
|
||||
super.removeViews(start, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewsInLayout(int start, int count) {
|
||||
for (int i = start; i < start + count; i++) {
|
||||
removeViewFromYogaTree(getChildAt(i), true);
|
||||
}
|
||||
super.removeViewsInLayout(start, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllViews() {
|
||||
final int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
removeViewFromYogaTree(getChildAt(i), false);
|
||||
}
|
||||
super.removeAllViews();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllViewsInLayout() {
|
||||
final int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
removeViewFromYogaTree(getChildAt(i), true);
|
||||
}
|
||||
super.removeAllViewsInLayout();
|
||||
}
|
||||
|
||||
private void removeViewFromYogaTree(View view, boolean inLayout) {
|
||||
final YogaNode node = mYogaNodes.get(view);
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final YogaNode parent = node.getParent();
|
||||
|
||||
for (int i = 0; i < parent.getChildCount(); i++) {
|
||||
if (parent.getChildAt(i).equals(node)) {
|
||||
parent.removeChildAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
node.setData(null);
|
||||
mYogaNodes.remove(view);
|
||||
|
||||
if (inLayout) {
|
||||
mYogaNode.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyLayoutRecursive(YogaNode node, float xOffset, float yOffset) {
|
||||
View view = (View) node.getData();
|
||||
if (view != null && view != this) {
|
||||
if (view.getVisibility() == GONE) {
|
||||
return;
|
||||
}
|
||||
view.measure(
|
||||
View.MeasureSpec.makeMeasureSpec(
|
||||
Math.round(node.getLayoutWidth()),
|
||||
View.MeasureSpec.EXACTLY),
|
||||
View.MeasureSpec.makeMeasureSpec(
|
||||
Math.round(node.getLayoutHeight()),
|
||||
View.MeasureSpec.EXACTLY));
|
||||
view.layout(
|
||||
Math.round(xOffset + node.getLayoutX()),
|
||||
Math.round(yOffset + node.getLayoutY()),
|
||||
Math.round(xOffset + node.getLayoutX() + node.getLayoutWidth()),
|
||||
Math.round(yOffset + node.getLayoutY() + node.getLayoutHeight()));
|
||||
}
|
||||
|
||||
final int childrenCount = node.getChildCount();
|
||||
for (int i = 0; i < childrenCount; i++) {
|
||||
if (this.equals(view)) {
|
||||
applyLayoutRecursive(node.getChildAt(i), xOffset, yOffset);
|
||||
} else if (view instanceof YogaLayout) {
|
||||
continue;
|
||||
} else {
|
||||
applyLayoutRecursive(
|
||||
node.getChildAt(i),
|
||||
xOffset + node.getLayoutX(),
|
||||
yOffset + node.getLayoutY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
// Either we are a root of a tree, or this function is called by our parent's onLayout, in which
|
||||
// case our r-l and b-t are the size of our node.
|
||||
if (!(getParent() instanceof YogaLayout) &&
|
||||
Math.round(mYogaNode.getLayoutHeight()) != b-t &&
|
||||
Math.round(mYogaNode.getLayoutWidth()) != r-l) {
|
||||
createLayout(
|
||||
MeasureSpec.makeMeasureSpec(r - l, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(b - t, MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
applyLayoutRecursive(mYogaNode, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is mostly unneeded, because Yoga is doing the measuring. Hence we only need to
|
||||
* return accurate results if we are the root.
|
||||
*
|
||||
* @param widthMeasureSpec the suggested specification for the width
|
||||
* @param heightMeasureSpec the suggested specification for the height
|
||||
*/
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (!(getParent() instanceof YogaLayout)) {
|
||||
createLayout(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
setMeasuredDimension(
|
||||
Math.round(mYogaNode.getLayoutWidth()),
|
||||
Math.round(mYogaNode.getLayoutHeight()));
|
||||
}
|
||||
|
||||
private void createLayout(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
|
||||
if (heightMode == MeasureSpec.EXACTLY) {
|
||||
mYogaNode.setHeight(heightSize);
|
||||
}
|
||||
if (widthMode == MeasureSpec.EXACTLY) {
|
||||
mYogaNode.setWidth(widthSize);
|
||||
}
|
||||
if (heightMode == MeasureSpec.AT_MOST) {
|
||||
mYogaNode.setMaxHeight(heightSize);
|
||||
}
|
||||
if (widthMode == MeasureSpec.AT_MOST) {
|
||||
mYogaNode.setMaxWidth(widthSize);
|
||||
}
|
||||
|
||||
mYogaNode.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the layout parameters to the YogaNode. That is, this function is a translator from
|
||||
* {@code yoga:X="Y"} to {@code yogaNode.setX(Y);}, with some reasonable defaults.
|
||||
*
|
||||
* <p>
|
||||
* If the SDK version is high enough, and the {@code yoga:direction} is not set on
|
||||
* the component, the direction (LTR or RTL) is set according to the locale.
|
||||
*
|
||||
* <p>
|
||||
* The attributes {@code padding_top}, {@code padding_right} etc. default to those of the view's
|
||||
* drawable background, if it has one.
|
||||
*
|
||||
* @param layoutParameters The source set of params
|
||||
* @param node The destination node
|
||||
*/
|
||||
protected static void applyLayoutParams(LayoutParams layoutParameters, YogaNode node, View view) {
|
||||
// JELLY_BEAN_MR1 (17) is the first version supporting getLayoutDirection()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
Configuration configuration = view.getResources().getConfiguration();
|
||||
if (configuration.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
|
||||
node.setDirection(YogaDirection.RTL);
|
||||
}
|
||||
}
|
||||
|
||||
Drawable background = view.getBackground();
|
||||
if (background != null) {
|
||||
final Rect backgroundPadding = new Rect();
|
||||
if (background.getPadding(backgroundPadding)) {
|
||||
node.setPadding(YogaEdge.LEFT, backgroundPadding.left);
|
||||
node.setPadding(YogaEdge.TOP, backgroundPadding.top);
|
||||
node.setPadding(YogaEdge.RIGHT, backgroundPadding.right);
|
||||
node.setPadding(YogaEdge.BOTTOM, backgroundPadding.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < layoutParameters.attributes.size(); i++) {
|
||||
final int attribute = layoutParameters.attributes.keyAt(i);
|
||||
final float value = layoutParameters.attributes.valueAt(i);
|
||||
|
||||
if (attribute == R.styleable.yoga_align_content) {
|
||||
node.setAlignContent(YogaAlign.fromInt(Math.round(value)));
|
||||
} else if (attribute == R.styleable.yoga_align_items) {
|
||||
node.setAlignItems(YogaAlign.fromInt(Math.round(value)));
|
||||
} else if (attribute == R.styleable.yoga_align_self) {
|
||||
node.setAlignSelf(YogaAlign.fromInt(Math.round(value)));
|
||||
} else if (attribute == R.styleable.yoga_aspect_ratio) {
|
||||
node.setAspectRatio(value);
|
||||
} else if (attribute == R.styleable.yoga_border_left) {
|
||||
node.setBorder(YogaEdge.LEFT, value);
|
||||
} else if (attribute == R.styleable.yoga_border_top) {
|
||||
node.setBorder(YogaEdge.TOP, value);
|
||||
} else if (attribute == R.styleable.yoga_border_right) {
|
||||
node.setBorder(YogaEdge.RIGHT, value);
|
||||
} else if (attribute == R.styleable.yoga_border_bottom) {
|
||||
node.setBorder(YogaEdge.BOTTOM, value);
|
||||
} else if (attribute == R.styleable.yoga_border_start) {
|
||||
node.setBorder(YogaEdge.START, value);
|
||||
} else if (attribute == R.styleable.yoga_border_end) {
|
||||
node.setBorder(YogaEdge.END, value);
|
||||
} else if (attribute == R.styleable.yoga_border_horizontal) {
|
||||
node.setBorder(YogaEdge.HORIZONTAL, value);
|
||||
} else if (attribute == R.styleable.yoga_border_vertical) {
|
||||
node.setBorder(YogaEdge.VERTICAL, value);
|
||||
} else if (attribute == R.styleable.yoga_border_all) {
|
||||
node.setBorder(YogaEdge.ALL, value);
|
||||
} else if (attribute == R.styleable.yoga_direction) {
|
||||
node.setDirection(YogaDirection.fromInt(Math.round(value)));
|
||||
} else if (attribute == R.styleable.yoga_flex) {
|
||||
node.setFlex(value);
|
||||
} else if (attribute == R.styleable.yoga_flex_basis) {
|
||||
node.setFlexBasis(value);
|
||||
} else if (attribute == R.styleable.yoga_flex_basis_percent) {
|
||||
node.setFlexBasisPercent(value);
|
||||
} else if (attribute == R.styleable.yoga_flex_direction) {
|
||||
node.setFlexDirection(YogaFlexDirection.fromInt(Math.round(value)));
|
||||
} else if (attribute == R.styleable.yoga_flex_grow) {
|
||||
node.setFlexGrow(value);
|
||||
} else if (attribute == R.styleable.yoga_flex_shrink) {
|
||||
node.setFlexShrink(value);
|
||||
} else if (attribute == R.styleable.yoga_height) {
|
||||
node.setHeight(value);
|
||||
} else if (attribute == R.styleable.yoga_height_percent) {
|
||||
node.setHeightPercent(value);
|
||||
} else if (attribute == R.styleable.yoga_margin_left) {
|
||||
node.setMargin(YogaEdge.LEFT, value);
|
||||
} else if (attribute == R.styleable.yoga_justify_content) {
|
||||
node.setJustifyContent(YogaJustify.fromInt(Math.round(value)));
|
||||
} else if (attribute == R.styleable.yoga_margin_top) {
|
||||
node.setMargin(YogaEdge.TOP, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_right) {
|
||||
node.setMargin(YogaEdge.RIGHT, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_bottom) {
|
||||
node.setMargin(YogaEdge.BOTTOM, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_start) {
|
||||
node.setMargin(YogaEdge.START, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_end) {
|
||||
node.setMargin(YogaEdge.END, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_horizontal) {
|
||||
node.setMargin(YogaEdge.HORIZONTAL, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_vertical) {
|
||||
node.setMargin(YogaEdge.VERTICAL, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_all) {
|
||||
node.setMargin(YogaEdge.ALL, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_percent_left) {
|
||||
node.setMarginPercent(YogaEdge.LEFT, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_percent_top) {
|
||||
node.setMarginPercent(YogaEdge.TOP, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_percent_right) {
|
||||
node.setMarginPercent(YogaEdge.RIGHT, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_percent_bottom) {
|
||||
node.setMarginPercent(YogaEdge.BOTTOM, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_percent_start) {
|
||||
node.setMarginPercent(YogaEdge.START, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_percent_end) {
|
||||
node.setMarginPercent(YogaEdge.END, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_percent_horizontal) {
|
||||
node.setMarginPercent(YogaEdge.HORIZONTAL, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_percent_vertical) {
|
||||
node.setMarginPercent(YogaEdge.VERTICAL, value);
|
||||
} else if (attribute == R.styleable.yoga_margin_percent_all) {
|
||||
node.setMarginPercent(YogaEdge.ALL, value);
|
||||
} else if (attribute == R.styleable.yoga_max_height) {
|
||||
node.setMaxHeight(value);
|
||||
} else if (attribute == R.styleable.yoga_max_height_percent) {
|
||||
node.setMaxHeightPercent(value);
|
||||
} else if (attribute == R.styleable.yoga_max_width) {
|
||||
node.setMaxWidth(value);
|
||||
} else if (attribute == R.styleable.yoga_max_width_percent) {
|
||||
node.setMaxWidthPercent(value);
|
||||
} else if (attribute == R.styleable.yoga_min_height) {
|
||||
node.setMinHeight(value);
|
||||
} else if (attribute == R.styleable.yoga_min_height_percent) {
|
||||
node.setMinHeightPercent(value);
|
||||
} else if (attribute == R.styleable.yoga_min_width) {
|
||||
node.setMinWidth(value);
|
||||
} else if (attribute == R.styleable.yoga_min_width_percent) {
|
||||
node.setMinWidthPercent(value);
|
||||
} else if (attribute == R.styleable.yoga_overflow) {
|
||||
node.setOverflow(YogaOverflow.fromInt(Math.round(value)));
|
||||
} else if (attribute == R.styleable.yoga_padding_left) {
|
||||
node.setPadding(YogaEdge.LEFT, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_top) {
|
||||
node.setPadding(YogaEdge.TOP, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_right) {
|
||||
node.setPadding(YogaEdge.RIGHT, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_bottom) {
|
||||
node.setPadding(YogaEdge.BOTTOM, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_start) {
|
||||
node.setPadding(YogaEdge.START, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_end) {
|
||||
node.setPadding(YogaEdge.END, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_horizontal) {
|
||||
node.setPadding(YogaEdge.HORIZONTAL, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_vertical) {
|
||||
node.setPadding(YogaEdge.VERTICAL, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_all) {
|
||||
node.setPadding(YogaEdge.ALL, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_percent_left) {
|
||||
node.setPaddingPercent(YogaEdge.LEFT, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_percent_top) {
|
||||
node.setPaddingPercent(YogaEdge.TOP, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_percent_right) {
|
||||
node.setPaddingPercent(YogaEdge.RIGHT, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_percent_bottom) {
|
||||
node.setPaddingPercent(YogaEdge.BOTTOM, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_percent_start) {
|
||||
node.setPaddingPercent(YogaEdge.START, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_percent_end) {
|
||||
node.setPaddingPercent(YogaEdge.END, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_percent_horizontal) {
|
||||
node.setPaddingPercent(YogaEdge.HORIZONTAL, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_percent_vertical) {
|
||||
node.setPaddingPercent(YogaEdge.VERTICAL, value);
|
||||
} else if (attribute == R.styleable.yoga_padding_percent_all) {
|
||||
node.setPaddingPercent(YogaEdge.ALL, value);
|
||||
} else if (attribute == R.styleable.yoga_position_left) {
|
||||
node.setPosition(YogaEdge.LEFT, value);
|
||||
} else if (attribute == R.styleable.yoga_position_top) {
|
||||
node.setPosition(YogaEdge.TOP, value);
|
||||
} else if (attribute == R.styleable.yoga_position_right) {
|
||||
node.setPosition(YogaEdge.RIGHT, value);
|
||||
} else if (attribute == R.styleable.yoga_position_bottom) {
|
||||
node.setPosition(YogaEdge.BOTTOM, value);
|
||||
} else if (attribute == R.styleable.yoga_position_start) {
|
||||
node.setPosition(YogaEdge.START, value);
|
||||
} else if (attribute == R.styleable.yoga_position_end) {
|
||||
node.setPosition(YogaEdge.END, value);
|
||||
} else if (attribute == R.styleable.yoga_position_horizontal) {
|
||||
node.setPosition(YogaEdge.HORIZONTAL, value);
|
||||
} else if (attribute == R.styleable.yoga_position_vertical) {
|
||||
node.setPosition(YogaEdge.VERTICAL, value);
|
||||
} else if (attribute == R.styleable.yoga_position_all) {
|
||||
node.setPosition(YogaEdge.ALL, value);
|
||||
} else if (attribute == R.styleable.yoga_position_percent_left) {
|
||||
node.setPositionPercent(YogaEdge.LEFT, value);
|
||||
} else if (attribute == R.styleable.yoga_position_percent_top) {
|
||||
node.setPositionPercent(YogaEdge.TOP, value);
|
||||
} else if (attribute == R.styleable.yoga_position_percent_right) {
|
||||
node.setPositionPercent(YogaEdge.RIGHT, value);
|
||||
} else if (attribute == R.styleable.yoga_position_percent_bottom) {
|
||||
node.setPositionPercent(YogaEdge.BOTTOM, value);
|
||||
} else if (attribute == R.styleable.yoga_position_percent_start) {
|
||||
node.setPositionPercent(YogaEdge.START, value);
|
||||
} else if (attribute == R.styleable.yoga_position_percent_end) {
|
||||
node.setPositionPercent(YogaEdge.END, value);
|
||||
} else if (attribute == R.styleable.yoga_position_percent_horizontal) {
|
||||
node.setPositionPercent(YogaEdge.HORIZONTAL, value);
|
||||
} else if (attribute == R.styleable.yoga_position_percent_vertical) {
|
||||
node.setPositionPercent(YogaEdge.VERTICAL, value);
|
||||
} else if (attribute == R.styleable.yoga_position_percent_all) {
|
||||
node.setPositionPercent(YogaEdge.ALL, value);
|
||||
} else if (attribute == R.styleable.yoga_position_type) {
|
||||
node.setPositionType(YogaPositionType.fromInt(Math.round(value)));
|
||||
} else if (attribute == R.styleable.yoga_width) {
|
||||
node.setWidth(value);
|
||||
} else if (attribute == R.styleable.yoga_width_percent) {
|
||||
node.setWidthPercent(value);
|
||||
} else if (attribute == R.styleable.yoga_wrap) {
|
||||
node.setWrap(YogaWrap.fromInt(Math.round(value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
|
||||
return new YogaLayout.LayoutParams(getContext(), attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
|
||||
return new YogaLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
|
||||
return new YogaLayout.LayoutParams(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
|
||||
return p instanceof LayoutParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code YogaLayout.LayoutParams} are used by views to tell {@link YogaLayout} how they want to
|
||||
* be laid out. More precisely, the specify the yoga parameters of the view.
|
||||
*
|
||||
* <p>
|
||||
* This is actually mostly a wrapper around a {@code SparseArray} that holds a mapping between
|
||||
* styleable id's ({@code R.styleable.yoga_*}) and the float of their values. In cases where the
|
||||
* value is an enum or an integer, they should first be cast to int (with rounding) before using.
|
||||
*/
|
||||
public static class LayoutParams extends ViewGroup.LayoutParams {
|
||||
|
||||
/**
|
||||
* A mapping from attribute keys ({@code R.styleable.yoga_*}) to the float of their values.
|
||||
* For attributes like position_percent_left (float), this is the native type. For attributes
|
||||
* like align_self (enums), the integer enum value is cast (rounding is used on the other side
|
||||
* to prevent precision errors). Dimension attributes are stored as float pixels.
|
||||
*/
|
||||
SparseArray<Float> attributes;
|
||||
|
||||
/**
|
||||
* Constructs a set of layout params from a source set. In the case that the source set is
|
||||
* actually a {@link YogaLayout.LayoutParams}, we can copy all the yoga attributes. Otherwise
|
||||
* we start with a blank slate.
|
||||
*
|
||||
* @param source The layout params to copy from
|
||||
*/
|
||||
public LayoutParams(ViewGroup.LayoutParams source) {
|
||||
super(source);
|
||||
if (source instanceof LayoutParams) {
|
||||
attributes = ((LayoutParams) source).attributes.clone();
|
||||
} else {
|
||||
attributes = new SparseArray<>();
|
||||
|
||||
// Negative values include MATCH_PARENT and WRAP_CONTENT
|
||||
if (source.width >= 0) {
|
||||
attributes.put(R.styleable.yoga_width, (float) width);
|
||||
}
|
||||
if (source.height >= 0) {
|
||||
attributes.put(R.styleable.yoga_height, (float) height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a set of layout params, given width and height specs. In this case, we can set
|
||||
* the {@code yoga:width} and {@code yoga:height} if we are given them explicitly. If other
|
||||
* options (such as {@code match_parent} or {@code wrap_content} are given, then the parent
|
||||
* LayoutParams will store them, and we deal with them during layout. (see
|
||||
* {@link YogaLayout#createLayout})
|
||||
*
|
||||
* @param width the requested width, either a pixel size, {@code WRAP_CONTENT} or
|
||||
* {@code MATCH_PARENT}.
|
||||
* @param height the requested height, either a pixel size, {@code WRAP_CONTENT} or
|
||||
* {@code MATCH_PARENT}.
|
||||
*/
|
||||
public LayoutParams(int width, int height) {
|
||||
super(width, height);
|
||||
attributes = new SparseArray<>();
|
||||
// Negative values include MATCH_PARENT and WRAP_CONTENT
|
||||
if (width >= 0) {
|
||||
attributes.put(R.styleable.yoga_width, (float) width);
|
||||
}
|
||||
if (height >= 0) {
|
||||
attributes.put(R.styleable.yoga_height, (float) height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a set of layout params, given attributes. Grabs all the {@code yoga:*}
|
||||
* defined in {@code ALL_YOGA_ATTRIBUTES} and collects the ones that are set in {@code attrs}.
|
||||
*
|
||||
* @param context the application environment
|
||||
* @param attrs the set of attributes from which to extract the yoga specific attributes
|
||||
*/
|
||||
public LayoutParams(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
attributes = new SparseArray<>();
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.yoga);
|
||||
|
||||
// Negative values include MATCH_PARENT and WRAP_CONTENT
|
||||
if (width >= 0) {
|
||||
attributes.put(R.styleable.yoga_width, (float) width);
|
||||
}
|
||||
if (height >= 0) {
|
||||
attributes.put(R.styleable.yoga_height, (float) height);
|
||||
}
|
||||
|
||||
final int attributeCount = a.getIndexCount();
|
||||
for (int i = 0; i < attributeCount; i++) {
|
||||
final int attribute = a.getIndex(i);
|
||||
final TypedValue val = new TypedValue();
|
||||
a.getValue(attribute, val);
|
||||
|
||||
if (val.type == TypedValue.TYPE_DIMENSION) {
|
||||
attributes.put(
|
||||
attribute,
|
||||
(float) a.getDimensionPixelSize(attribute, 0));
|
||||
} else {
|
||||
attributes.put(attribute, a.getFloat(attribute, 0));
|
||||
}
|
||||
}
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around measure function for yoga leaves.
|
||||
*/
|
||||
public static class ViewMeasureFunction implements YogaMeasureFunction {
|
||||
|
||||
/**
|
||||
* A function to measure leaves of the Yoga tree. Yoga needs some way to know how large
|
||||
* elements want to be. This function passes that question directly through to the relevant
|
||||
* {@code View}'s measure function.
|
||||
*
|
||||
* @param node The yoga node to measure
|
||||
* @param width The suggested width from the parent
|
||||
* @param widthMode The type of suggestion for the width
|
||||
* @param height The suggested height from the parent
|
||||
* @param heightMode The type of suggestion for the height
|
||||
* @return A measurement output ({@code YogaMeasureOutput}) for the node
|
||||
*/
|
||||
public long measure(
|
||||
YogaNodeAPI node,
|
||||
float width,
|
||||
YogaMeasureMode widthMode,
|
||||
float height,
|
||||
YogaMeasureMode heightMode) {
|
||||
final View view = (View) node.getData();
|
||||
if (view == null || view instanceof YogaLayout) {
|
||||
return YogaMeasureOutput.make(0, 0);
|
||||
}
|
||||
|
||||
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(
|
||||
(int) width,
|
||||
viewMeasureSpecFromYogaMeasureMode(widthMode));
|
||||
final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(
|
||||
(int) height,
|
||||
viewMeasureSpecFromYogaMeasureMode(heightMode));
|
||||
|
||||
view.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
return YogaMeasureOutput.make(view.getMeasuredWidth(), view.getMeasuredHeight());
|
||||
}
|
||||
|
||||
private int viewMeasureSpecFromYogaMeasureMode(YogaMeasureMode mode) {
|
||||
if (mode == YogaMeasureMode.AT_MOST) {
|
||||
return MeasureSpec.AT_MOST;
|
||||
} else if (mode == YogaMeasureMode.EXACTLY) {
|
||||
return MeasureSpec.EXACTLY;
|
||||
} else {
|
||||
return MeasureSpec.UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.yoga.android;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* A layout inflater factory. This provides our custom {@link YogaViewLayoutFactory#onCreateView}
|
||||
* to the XML inflation system, allowing us to replace XML tags.
|
||||
*/
|
||||
public class YogaViewLayoutFactory implements LayoutInflater.Factory {
|
||||
private static YogaViewLayoutFactory sYogaViewLayoutFactory;
|
||||
|
||||
/**
|
||||
* Obtains (and initialises if necessary) the singleton {@link YogaViewLayoutFactory}.
|
||||
*
|
||||
* @return The singleton instance
|
||||
*/
|
||||
public static YogaViewLayoutFactory getInstance() {
|
||||
if (sYogaViewLayoutFactory == null) {
|
||||
sYogaViewLayoutFactory = new YogaViewLayoutFactory();
|
||||
}
|
||||
return sYogaViewLayoutFactory;
|
||||
}
|
||||
|
||||
YogaViewLayoutFactory() {}
|
||||
|
||||
/**
|
||||
* Hook for inflating from a LayoutInflater. This hook replaces the cumbersome
|
||||
* {@code com.facebook.etc.YogaLayout} with simply {@code YogaLayout} in your XML and the same
|
||||
* with {@code VirtualYogaLayout}.
|
||||
*
|
||||
* @param name Tag name to be inflated.
|
||||
* @param context The context the view is being created in.
|
||||
* @param attrs Inflation attributes as specified in XML file.
|
||||
*
|
||||
* @return View Newly created view. Return null for the default behavior.
|
||||
*/
|
||||
@Override
|
||||
public View onCreateView(String name, Context context, AttributeSet attrs) {
|
||||
if (YogaLayout.class.getSimpleName().equals(name)) {
|
||||
return new YogaLayout(context, attrs);
|
||||
}
|
||||
if (VirtualYogaLayout.class.getSimpleName().equals(name)) {
|
||||
return new VirtualYogaLayout(context, attrs);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
185
android/src/main/res/values/attrs.xml
Normal file
@@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2014-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the BSD-style license found in the
|
||||
LICENSE file in the root directory of this source tree. An additional grant
|
||||
of patent rights can be found in the PATENTS file in the same directory.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<declare-styleable name="yoga">
|
||||
|
||||
<attr name="align_content" format="enum">
|
||||
<enum name="auto" value="0"/>
|
||||
<enum name="flex_start" value="1"/>
|
||||
<enum name="center" value="2"/>
|
||||
<enum name="flex_end" value="3"/>
|
||||
<enum name="stretch" value="4"/>
|
||||
<enum name="baseline" value="5"/>
|
||||
</attr>
|
||||
|
||||
<attr name="align_items" format="enum">
|
||||
<enum name="auto" value="0"/>
|
||||
<enum name="flex_start" value="1"/>
|
||||
<enum name="center" value="2"/>
|
||||
<enum name="flex_end" value="3"/>
|
||||
<enum name="stretch" value="4"/>
|
||||
<enum name="baseline" value="5"/>
|
||||
</attr>
|
||||
|
||||
<attr name="align_self" format="enum">
|
||||
<enum name="auto" value="0"/>
|
||||
<enum name="flex_start" value="1"/>
|
||||
<enum name="center" value="2"/>
|
||||
<enum name="flex_end" value="3"/>
|
||||
<enum name="stretch" value="4"/>
|
||||
<enum name="baseline" value="5"/>
|
||||
</attr>
|
||||
|
||||
<attr name="aspect_ratio" format="float"/>
|
||||
|
||||
<attr name="border_left" format="dimension"/>
|
||||
<attr name="border_top" format="dimension"/>
|
||||
<attr name="border_right" format="dimension"/>
|
||||
<attr name="border_bottom" format="dimension"/>
|
||||
<attr name="border_start" format="dimension"/>
|
||||
<attr name="border_end" format="dimension"/>
|
||||
<attr name="border_horizontal" format="dimension"/>
|
||||
<attr name="border_vertical" format="dimension"/>
|
||||
<attr name="border_all" format="dimension"/>
|
||||
|
||||
<attr name="direction" format="enum">
|
||||
<enum name="inherit" value="0"/>
|
||||
<enum name="ltr" value="1"/>
|
||||
<enum name="rtl" value="2"/>
|
||||
</attr>
|
||||
|
||||
<attr name="flex" format="float"/>
|
||||
|
||||
<attr name="flex_basis" format="float"/>
|
||||
|
||||
<attr name="flex_basis_percent" format="float"/>
|
||||
|
||||
<attr name="flex_direction" format="enum">
|
||||
<enum name="column" value="0"/>
|
||||
<enum name="column_reverse" value="1"/>
|
||||
<enum name="row" value="2"/>
|
||||
<enum name="row_reverse" value="3"/>
|
||||
</attr>
|
||||
|
||||
<attr name="flex_grow" format="float"/>
|
||||
|
||||
<attr name="flex_shrink" format="float"/>
|
||||
|
||||
<attr name="height" format="dimension"/>
|
||||
|
||||
<attr name="height_percent" format="float"/>
|
||||
|
||||
<attr name="justify_content" format="enum">
|
||||
<enum name="flex_start" value="0"/>
|
||||
<enum name="center" value="1"/>
|
||||
<enum name="flex_end" value="2"/>
|
||||
<enum name="space_between" value="3"/>
|
||||
<enum name="space_around" value="4"/>
|
||||
</attr>
|
||||
|
||||
<attr name="margin_left" format="dimension"/>
|
||||
<attr name="margin_top" format="dimension"/>
|
||||
<attr name="margin_right" format="dimension"/>
|
||||
<attr name="margin_bottom" format="dimension"/>
|
||||
<attr name="margin_start" format="dimension"/>
|
||||
<attr name="margin_end" format="dimension"/>
|
||||
<attr name="margin_horizontal" format="dimension"/>
|
||||
<attr name="margin_vertical" format="dimension"/>
|
||||
<attr name="margin_all" format="dimension"/>
|
||||
|
||||
<attr name="margin_percent_left" format="dimension"/>
|
||||
<attr name="margin_percent_top" format="dimension"/>
|
||||
<attr name="margin_percent_right" format="dimension"/>
|
||||
<attr name="margin_percent_bottom" format="dimension"/>
|
||||
<attr name="margin_percent_start" format="dimension"/>
|
||||
<attr name="margin_percent_end" format="dimension"/>
|
||||
<attr name="margin_percent_horizontal" format="dimension"/>
|
||||
<attr name="margin_percent_vertical" format="dimension"/>
|
||||
<attr name="margin_percent_all" format="dimension"/>
|
||||
|
||||
<attr name="max_height" format="dimension"/>
|
||||
|
||||
<attr name="max_height_percent" format="float"/>
|
||||
|
||||
<attr name="max_width" format="dimension"/>
|
||||
|
||||
<attr name="max_width_percent" format="float"/>
|
||||
|
||||
<attr name="min_height" format="dimension"/>
|
||||
|
||||
<attr name="min_height_percent" format="float"/>
|
||||
|
||||
<attr name="min_width" format="dimension"/>
|
||||
|
||||
<attr name="min_width_percent" format="float"/>
|
||||
|
||||
<attr name="overflow" format="enum">
|
||||
<enum name="visible" value="0"/>
|
||||
<enum name="hidden" value="1"/>
|
||||
<enum name="scroll" value="2"/>
|
||||
</attr>
|
||||
|
||||
<attr name="padding_left" format="dimension"/>
|
||||
<attr name="padding_top" format="dimension"/>
|
||||
<attr name="padding_right" format="dimension"/>
|
||||
<attr name="padding_bottom" format="dimension"/>
|
||||
<attr name="padding_start" format="dimension"/>
|
||||
<attr name="padding_end" format="dimension"/>
|
||||
<attr name="padding_horizontal" format="dimension"/>
|
||||
<attr name="padding_vertical" format="dimension"/>
|
||||
<attr name="padding_all" format="dimension"/>
|
||||
|
||||
<attr name="padding_percent_left" format="float"/>
|
||||
<attr name="padding_percent_top" format="float"/>
|
||||
<attr name="padding_percent_right" format="float"/>
|
||||
<attr name="padding_percent_bottom" format="float"/>
|
||||
<attr name="padding_percent_start" format="float"/>
|
||||
<attr name="padding_percent_end" format="float"/>
|
||||
<attr name="padding_percent_horizontal" format="float"/>
|
||||
<attr name="padding_percent_vertical" format="float"/>
|
||||
<attr name="padding_percent_all" format="float"/>
|
||||
|
||||
<attr name="position_left" format="dimension"/>
|
||||
<attr name="position_top" format="dimension"/>
|
||||
<attr name="position_right" format="dimension"/>
|
||||
<attr name="position_bottom" format="dimension"/>
|
||||
<attr name="position_start" format="dimension"/>
|
||||
<attr name="position_end" format="dimension"/>
|
||||
<attr name="position_horizontal" format="dimension"/>
|
||||
<attr name="position_vertical" format="dimension"/>
|
||||
<attr name="position_all" format="dimension"/>
|
||||
|
||||
<attr name="position_percent_left" format="float"/>
|
||||
<attr name="position_percent_top" format="float"/>
|
||||
<attr name="position_percent_right" format="float"/>
|
||||
<attr name="position_percent_bottom" format="float"/>
|
||||
<attr name="position_percent_start" format="float"/>
|
||||
<attr name="position_percent_end" format="float"/>
|
||||
<attr name="position_percent_horizontal" format="float"/>
|
||||
<attr name="position_percent_vertical" format="float"/>
|
||||
<attr name="position_percent_all" format="float"/>
|
||||
|
||||
<attr name="position_type" format="enum">
|
||||
<enum name="relative" value="0"/>
|
||||
<enum name="absolute" value="1"/>
|
||||
</attr>
|
||||
|
||||
<attr name="width" format="dimension"/>
|
||||
|
||||
<attr name="width_percent" format="float"/>
|
||||
|
||||
<attr name="wrap" format="enum">
|
||||
<enum name="no_wrap" value="0"/>
|
||||
<enum name="wrap" value="1"/>
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
</resources>
|
@@ -21,7 +21,7 @@ cxx_binary(
|
||||
'-std=c11',
|
||||
],
|
||||
deps = [
|
||||
csslayout_dep(':CSSLayout'),
|
||||
yoga_dep(':yoga'),
|
||||
],
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
@@ -9,13 +9,13 @@
|
||||
|
||||
#include "YGBenchmark.h"
|
||||
|
||||
#include <CSSLayout/Yoga.h>
|
||||
#include <yoga/Yoga.h>
|
||||
|
||||
static YGSize _measure(YGNodeRef node,
|
||||
float width,
|
||||
YGMeasureMode widthMode,
|
||||
float height,
|
||||
YGMeasureMode heightMode) {
|
||||
float width,
|
||||
YGMeasureMode widthMode,
|
||||
float height,
|
||||
YGMeasureMode heightMode) {
|
||||
return (YGSize){
|
||||
.width = widthMode == YGMeasureModeUndefined ? 10 : width,
|
||||
.height = heightMode == YGMeasureModeUndefined ? 10 : width,
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
#define NUM_REPETITIONS 1000
|
||||
|
||||
#define YGBENCHMARKS(BLOCK) \
|
||||
#define YGBENCHMARKS(BLOCK) \
|
||||
int main(int argc, char const *argv[]) { \
|
||||
clock_t __start; \
|
||||
clock_t __endTimes[NUM_REPETITIONS]; \
|
||||
@@ -25,7 +25,7 @@
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define YGBENCHMARK(NAME, BLOCK) \
|
||||
#define YGBENCHMARK(NAME, BLOCK) \
|
||||
__start = clock(); \
|
||||
for (uint32_t __i = 0; __i < NUM_REPETITIONS; __i++) { \
|
||||
{ BLOCK } \
|
||||
|
31
build.gradle
Normal file
@@ -0,0 +1,31 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.2'
|
||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
|
||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
|
||||
classpath 'com.nabilhachicha:android-native-dependencies:0.1'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs "${rootDir}/lib/jsr-305"
|
||||
dirs "${rootDir}/lib/soloader"
|
||||
dirs "${rootDir}/lib/appcompat"
|
||||
dirs "${rootDir}/lib/android-support"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
6
csharp/.gitignore
vendored
@@ -34,6 +34,10 @@ bld/
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
tests/Facebook.Yoga/NUnit-[0-9\.]*/
|
||||
tests/Facebook.Yoga/YogaTest.dll
|
||||
tests/Facebook.Yoga/YogaTest.dll.mdb
|
||||
tests/Facebook.Yoga/libyoga.dylib
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
@@ -262,4 +266,4 @@ paket-files/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyc
|
||||
|
@@ -34,6 +34,10 @@ bld/
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
tests/Facebook.Yoga/NUnit-[0-9\.]*/
|
||||
tests/Facebook.Yoga/YogaTest.dll
|
||||
tests/Facebook.Yoga/YogaTest.dll.mdb
|
||||
tests/Facebook.Yoga/libyoga.dylib
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
@@ -262,4 +266,4 @@ paket-files/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyc
|
||||
|
1
csharp/Android/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
lib/
|
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2021459E-8FB1-44A4-89F1-E291769CD2C6}</ProjectGuid>
|
||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Facebook.Yoga.Android.Tests</RootNamespace>
|
||||
<AssemblyName>Facebook.Yoga.Android.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v7.1</TargetFrameworkVersion>
|
||||
<AndroidApplication>True</AndroidApplication>
|
||||
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
|
||||
<AndroidResgenClass>Resource</AndroidResgenClass>
|
||||
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
||||
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
||||
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
|
||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||
<AndroidTlsProvider></AndroidTlsProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidManagedSymbols>true</AndroidManagedSymbols>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Mono.Android" />
|
||||
<Reference Include="Xamarin.Android.NUnitLite" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="MainActivity.cs" />
|
||||
<Compile Include="Resources\Resource.designer.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Properties\AndroidManifest.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Facebook.Yoga.Android\Facebook.Yoga.Android.csproj">
|
||||
<Project>{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}</Project>
|
||||
<Name>Facebook.Yoga.Android</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="..\..\tests\Facebook.Yoga\Facebook.Yoga.Shared.Tests.projitems" Label="Shared" Condition="Exists('..\..\tests\Facebook.Yoga\Facebook.Yoga.Shared.Tests.projitems')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
</Project>
|
25
csharp/Android/Facebook.Yoga.Android.Tests/MainActivity.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE-examples file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System.Reflection;
|
||||
using Android.App;
|
||||
using Android.OS;
|
||||
using Xamarin.Android.NUnitLite;
|
||||
|
||||
namespace Facebook.Yoga.Android.Tests
|
||||
{
|
||||
[Activity(Label = "Facebook.Yoga.Android.Tests", MainLauncher = true)]
|
||||
public class MainActivity : TestSuiteActivity
|
||||
{
|
||||
protected override void OnCreate(Bundle bundle)
|
||||
{
|
||||
AddTest(Assembly.GetExecutingAssembly());
|
||||
base.OnCreate(bundle);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
package="Facebook.Yoga.Android.Tests">
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="19" />
|
||||
|
||||
<application
|
||||
android:label="Facebook.Yoga.Android.Tests">
|
||||
</application>
|
||||
|
||||
</manifest>
|
0
csharp/Android/Facebook.Yoga.Android.Tests/Resources/Resource.designer.cs
generated
Normal file
33
csharp/Android/Facebook.Yoga.Android.sln
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Android.Tests", "Facebook.Yoga.Android.Tests\Facebook.Yoga.Android.Tests.csproj", "{2021459E-8FB1-44A4-89F1-E291769CD2C6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Android", "Facebook.Yoga.Android\Facebook.Yoga.Android.csproj", "{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{4804A8E6-E7B7-4F9E-A446-3DE8E73DB38A}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Facebook.Yoga.Shared", "..\Facebook.Yoga\Facebook.Yoga.Shared.shproj", "{91C42D32-291D-4B72-90B4-551663D60B8B}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Facebook.Yoga.Shared.Tests", "..\tests\Facebook.Yoga\Facebook.Yoga.Shared.Tests.shproj", "{4EDC82D9-A201-4831-8FE0-98F468F8E4AE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{91C42D32-291D-4B72-90B4-551663D60B8B} = {4804A8E6-E7B7-4F9E-A446-3DE8E73DB38A}
|
||||
{4EDC82D9-A201-4831-8FE0-98F468F8E4AE} = {4804A8E6-E7B7-4F9E-A446-3DE8E73DB38A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<BuildDependsOn>NativeLibraryARMV7;NativeLibraryX86;$(BuildDependsOn)</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
<Target Name="NativeLibraryARMV7" Outputs="$(ProjectDir)/lib/armeabi-v7a/libyoga.so">
|
||||
<Exec WorkingDirectory="$(ProjectDir)" Command="$(ProjectDir)../../Mac/buck-build.sh //csharp:yoganet#android-armv7,shared" />
|
||||
<Copy SourceFiles="$(ProjectDir)../../../buck-out/gen/csharp/yoganet#android-armv7,shared/libyoga.so" DestinationFiles="$(ProjectDir)/lib/armeabi-v7a/libyoga.so" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
<!--
|
||||
<Target Name="NativeLibraryARM64" Outputs="$(ProjectDir)/lib/arm64-v8a/libyoga.so">
|
||||
<Exec WorkingDirectory="$(ProjectDir)" Command="$(ProjectDir)../../Mac/buck-build.sh //csharp:yoganet#android-arm64,shared" />
|
||||
<Copy SourceFiles="$(ProjectDir)../../../buck-out/gen/csharp/yoganet#android-arm64,shared/libyoga.so" DestinationFiles="$(ProjectDir)/lib/arm64-v8/libyoga.so" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
-->
|
||||
<Target Name="NativeLibraryX86" Outputs="$(ProjectDir)/lib/x86/libyoga.so">
|
||||
<Exec WorkingDirectory="$(ProjectDir)" Command="$(ProjectDir)../../Mac/buck-build.sh //csharp:yoganet#android-x86,shared" />
|
||||
<Copy SourceFiles="$(ProjectDir)../../../buck-out/gen/csharp/yoganet#android-x86,shared/libyoga.so" DestinationFiles="$(ProjectDir)/lib/x86/libyoga.so" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
</Project>
|
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}</ProjectGuid>
|
||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Facebook.Yoga.Android</RootNamespace>
|
||||
<AssemblyName>Facebook.Yoga</AssemblyName>
|
||||
<TargetFrameworkVersion>v7.1</TargetFrameworkVersion>
|
||||
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
|
||||
<AndroidResgenClass>Resource</AndroidResgenClass>
|
||||
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
||||
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
||||
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
|
||||
<AndroidTlsProvider></AndroidTlsProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
<AndroidSupportedAbis>arm64-v8a;armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidManagedSymbols>true</AndroidManagedSymbols>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Mono.Android" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CustomBuildAction.targets" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="lib\x86\" />
|
||||
<Folder Include="lib\armeabi-v7a\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedNativeLibrary Include="lib\x86\libyoga.so">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedNativeLibrary>
|
||||
<EmbeddedNativeLibrary Include="lib\armeabi-v7a\libyoga.so">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedNativeLibrary>
|
||||
</ItemGroup>
|
||||
<Import Project="..\..\Facebook.Yoga\Facebook.Yoga.Shared.projitems" Label="Shared" Condition="Exists('..\..\Facebook.Yoga\Facebook.Yoga.Shared.projitems')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<Import Project="CustomBuildAction.targets" />
|
||||
</Project>
|
0
csharp/Android/Facebook.Yoga.Android/Resources/Resource.designer.cs
generated
Normal file
58
csharp/BUCK
@@ -5,16 +5,70 @@
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
include_defs('//YOGA_DEFS')
|
||||
|
||||
COMPILER_FLAGS = BASE_COMPILER_FLAGS + ['-std=c++11']
|
||||
|
||||
csharp_library(
|
||||
name = 'csslibnet46',
|
||||
name = 'yogalibnet46',
|
||||
dll_name = 'Facebook.Yoga.dll',
|
||||
framework_ver = 'net46',
|
||||
srcs = glob(['**/*.cs']),
|
||||
)
|
||||
|
||||
csharp_library(
|
||||
name = 'csslibnet45',
|
||||
name = 'yogalibnet45',
|
||||
dll_name = 'Facebook.Yoga.dll',
|
||||
framework_ver = 'net45',
|
||||
srcs = glob(['**/*.cs']),
|
||||
)
|
||||
|
||||
cxx_library(
|
||||
name = 'yoganet',
|
||||
soname = 'libyoga.$(ext)',
|
||||
srcs = glob(['Yoga/YGInterop.cpp']),
|
||||
compiler_flags = COMPILER_FLAGS,
|
||||
link_style = 'static',
|
||||
link_whole = True,
|
||||
deps = [yoga_dep(':yoga')],
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
||||
if isdir('/Applications/Xcode.app'):
|
||||
yoganet_ios_srcs = []
|
||||
for arch in [
|
||||
'iphonesimulator-x86_64', 'iphonesimulator-i386', 'iphoneos-arm64', 'iphoneos-armv7'
|
||||
]:
|
||||
name = 'yoganet-' + arch
|
||||
yoganet_ios_srcs.append(':' + name)
|
||||
genrule(
|
||||
name = name,
|
||||
srcs = [
|
||||
yoga_dep(':yoga#%s,static' % arch),
|
||||
yoga_dep('YogaKit:YogaKit#%s,static' % arch),
|
||||
yoga_dep('csharp:yoganet#%s,static' % arch),
|
||||
],
|
||||
out = 'libyoga-%s.a' % arch,
|
||||
cmd = 'libtool -static -o $OUT $SRCS',
|
||||
visibility = [yoga_dep('csharp:yoganet-ios')],
|
||||
)
|
||||
|
||||
genrule(
|
||||
name = 'yoganet-ios',
|
||||
srcs = yoganet_ios_srcs,
|
||||
out = 'libyoga.a',
|
||||
cmd = 'lipo $SRCS -create -output $OUT',
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
||||
yoganet_macosx_target = 'csharp:yoganet#macosx-%s,dynamic'
|
||||
genrule(
|
||||
name = 'yoganet-macosx',
|
||||
srcs = [
|
||||
yoga_dep(yoganet_macosx_target % 'x86_64'),
|
||||
yoga_dep(yoganet_macosx_target % 'i386'),
|
||||
],
|
||||
out = 'libyoga.dylib',
|
||||
cmd = 'lipo $SRCS -create -output $OUT',
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
130
csharp/Facebook.Yoga.Xamarin.sln
Normal file
@@ -0,0 +1,130 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{B674A497-DC8E-4286-A889-0C004235AA18}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iOS", "iOS", "{AC14A7DE-A180-46EC-8A88-77F60E73A099}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{09905D88-652D-4A72-8521-6CB1AF347795}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "macOS", "macOS", "{9BDE3670-188E-470F-9B89-CEC0EB042AB5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.iOS", "iOS\Facebook.Yoga.iOS\Facebook.Yoga.iOS.csproj", "{128FB32A-C4A1-4363-BF06-0A36E700B7FA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.iOS.Tests", "iOS\Facebook.Yoga.iOS.Tests\Facebook.Yoga.iOS.Tests.csproj", "{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Facebook.Yoga.Shared", "Facebook.Yoga\Facebook.Yoga.Shared.shproj", "{91C42D32-291D-4B72-90B4-551663D60B8B}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Facebook.Yoga.Shared.Tests", "tests\Facebook.Yoga\Facebook.Yoga.Shared.Tests.shproj", "{4EDC82D9-A201-4831-8FE0-98F468F8E4AE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Android", "Android\Facebook.Yoga.Android\Facebook.Yoga.Android.csproj", "{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Android.Tests", "Android\Facebook.Yoga.Android.Tests\Facebook.Yoga.Android.Tests.csproj", "{2021459E-8FB1-44A4-89F1-E291769CD2C6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuspec", "nuspec", "{2C3685DB-91B9-4207-9446-1C513DB36978}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
nuget\Facebook.Yoga.dll.config = nuget\Facebook.Yoga.dll.config
|
||||
nuget\Facebook.Yoga.nuspec = nuget\Facebook.Yoga.nuspec
|
||||
nuget\Facebook.Yoga.OSX.targets = nuget\Facebook.Yoga.OSX.targets
|
||||
nuget\Facebook.Yoga.targets = nuget\Facebook.Yoga.targets
|
||||
nuget\Facebook.Yoga.Universal.targets = nuget\Facebook.Yoga.Universal.targets
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Mac", "Mac\Facebook.Yoga.Mac.csproj", "{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Mac.Tests", "Mac\Facebook.Yoga.Mac.Tests\Facebook.Yoga.Mac.Tests.csproj", "{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Debug|iPhoneSimulator = Debug|iPhoneSimulator
|
||||
Release|iPhone = Release|iPhone
|
||||
Release|iPhoneSimulator = Release|iPhoneSimulator
|
||||
Debug|iPhone = Debug|iPhone
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|Any CPU.ActiveCfg = Release|iPhone
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|Any CPU.Build.0 = Release|iPhone
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|iPhone.ActiveCfg = Release|iPhone
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|iPhone.Build.0 = Release|iPhone
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|iPhone.ActiveCfg = Debug|iPhone
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|iPhone.Build.0 = Debug|iPhone
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{128FB32A-C4A1-4363-BF06-0A36E700B7FA} = {AC14A7DE-A180-46EC-8A88-77F60E73A099}
|
||||
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71} = {AC14A7DE-A180-46EC-8A88-77F60E73A099}
|
||||
{91C42D32-291D-4B72-90B4-551663D60B8B} = {09905D88-652D-4A72-8521-6CB1AF347795}
|
||||
{4EDC82D9-A201-4831-8FE0-98F468F8E4AE} = {09905D88-652D-4A72-8521-6CB1AF347795}
|
||||
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363} = {B674A497-DC8E-4286-A889-0C004235AA18}
|
||||
{2021459E-8FB1-44A4-89F1-E291769CD2C6} = {B674A497-DC8E-4286-A889-0C004235AA18}
|
||||
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71} = {9BDE3670-188E-470F-9B89-CEC0EB042AB5}
|
||||
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77} = {9BDE3670-188E-470F-9B89-CEC0EB042AB5}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@@ -1,46 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Yoga", "Yoga\Yoga.vcxproj", "{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Facebook.Yoga", "Facebook.Yoga\Facebook.Yoga.xproj", "{75BB7605-E54B-4EDE-8F5A-FF1F24464236}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Debug|x64.Build.0 = Debug|x64
|
||||
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Debug|x86.Build.0 = Debug|Win32
|
||||
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Release|x64.ActiveCfg = Release|x64
|
||||
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Release|x64.Build.0 = Release|x64
|
||||
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Release|x86.Build.0 = Release|Win32
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|x64.Build.0 = Release|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
13
csharp/Facebook.Yoga/BaselineFunction.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
namespace Facebook.Yoga
|
||||
{
|
||||
public delegate float BaselineFunction(YogaNode node, float width, float height);
|
||||
}
|
41
csharp/Facebook.Yoga/Facebook.Yoga.Shared.projitems
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<HasSharedItems>true</HasSharedItems>
|
||||
<SharedGUID>91c42d32-291d-4b72-90b4-551663d60b8b</SharedGUID>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<Import_RootNamespace>Facebook.Yoga.Shared</Import_RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)BaselineFunction.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)MeasureFunction.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)MeasureOutput.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Native.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaAlign.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaBaselineFunc.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaConstants.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaDimension.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaDirection.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaDisplay.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaEdge.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaExperimentalFeature.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaFlexDirection.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaJustify.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaLogger.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaLogLevel.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaMeasureFunc.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaMeasureMode.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaNode.Spacing.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaNode.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaOverflow.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaPositionType.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaPrintOptions.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaSize.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaUnit.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaValue.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaValueExtensions.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)YogaWrap.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
13
csharp/Facebook.Yoga/Facebook.Yoga.Shared.shproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>91c42d32-291d-4b72-90b4-551663d60b8b</ProjectGuid>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
|
||||
<PropertyGroup />
|
||||
<Import Project="Facebook.Yoga.Shared.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
|
||||
</Project>
|
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>75bb7605-e54b-4ede-8f5a-ff1f24464236</ProjectGuid>
|
||||
<RootNamespace>Facebook.Yoga</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace Facebook.Yoga
|
||||
{
|
||||
public delegate long MeasureFunction(
|
||||
public delegate YogaSize MeasureFunction(
|
||||
YogaNode node,
|
||||
float width,
|
||||
YogaMeasureMode widthMode,
|
||||
|
@@ -11,24 +11,9 @@ namespace Facebook.Yoga
|
||||
{
|
||||
public class MeasureOutput
|
||||
{
|
||||
public static long Make(double width, double height)
|
||||
public static YogaSize Make(float width, float height)
|
||||
{
|
||||
return Make((int) width, (int) height);
|
||||
}
|
||||
|
||||
public static long Make(int width, int height)
|
||||
{
|
||||
return (long)(((ulong) width) << 32 | ((uint) height));
|
||||
}
|
||||
|
||||
public static int GetWidth(long measureOutput)
|
||||
{
|
||||
return (int) (0xFFFFFFFF & (measureOutput >> 32));
|
||||
}
|
||||
|
||||
public static int GetHeight(long measureOutput)
|
||||
{
|
||||
return (int) (0xFFFFFFFF & measureOutput);
|
||||
return new YogaSize { width = width, height = height};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -14,272 +14,381 @@ namespace Facebook.Yoga
|
||||
{
|
||||
internal static class Native
|
||||
{
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||
private const string DllName = "__Internal";
|
||||
#else
|
||||
private const string DllName = "yoga";
|
||||
#endif
|
||||
|
||||
[DllImport(DllName)]
|
||||
internal class YGNodeHandle : SafeHandle
|
||||
{
|
||||
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||
private GCHandle _managed;
|
||||
#endif
|
||||
|
||||
private YGNodeHandle() : base(IntPtr.Zero, true)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvalid
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.handle == IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||
if (_managed.IsAllocated)
|
||||
{
|
||||
_managed.Free();
|
||||
}
|
||||
#endif
|
||||
Native.YGNodeFree(this.handle);
|
||||
GC.KeepAlive(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||
public void SetContext(YogaNode node)
|
||||
{
|
||||
if (!_managed.IsAllocated)
|
||||
{
|
||||
_managed = GCHandle.Alloc(node, GCHandleType.Weak);
|
||||
Native.YGNodeSetContext(this.handle, GCHandle.ToIntPtr(_managed));
|
||||
}
|
||||
}
|
||||
|
||||
public static YogaNode GetManaged(IntPtr ygNodePtr)
|
||||
{
|
||||
var node =
|
||||
GCHandle.FromIntPtr(Native.YGNodeGetContext(ygNodePtr)).Target as YogaNode;
|
||||
if (node == null)
|
||||
{
|
||||
throw new InvalidOperationException("YogaNode is already deallocated");
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGInteropSetLogger(
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)] YogaLogger.Func func);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern IntPtr YGNodeNew();
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YGNodeHandle YGNodeNew();
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeInit(IntPtr cssNode);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeFree(IntPtr node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeFree(IntPtr cssNode);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeReset(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeReset(IntPtr cssNode);
|
||||
|
||||
[DllImport(DllName)]
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int YGNodeGetInstanceCount();
|
||||
|
||||
[DllImport(DllName)]
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGSetExperimentalFeatureEnabled(
|
||||
YogaExperimentalFeature feature,
|
||||
bool enabled);
|
||||
|
||||
[DllImport(DllName)]
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool YGIsExperimentalFeatureEnabled(
|
||||
YogaExperimentalFeature feature);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeInsertChild(IntPtr node, IntPtr child, uint index);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeInsertChild(
|
||||
YGNodeHandle node,
|
||||
YGNodeHandle child,
|
||||
uint index);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeRemoveChild(IntPtr node, IntPtr child);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeRemoveChild(YGNodeHandle node, YGNodeHandle child);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern IntPtr YGNodeGetChild(IntPtr node, uint index);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeCalculateLayout(
|
||||
YGNodeHandle node,
|
||||
float availableWidth,
|
||||
float availableHeight,
|
||||
YogaDirection parentDirection);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern uint YGNodeChildCount(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeMarkDirty(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeCalculateLayout(IntPtr node,
|
||||
float availableWidth,
|
||||
float availableHeight,
|
||||
YogaDirection parentDirection);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeMarkDirty(IntPtr node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public static extern bool YGNodeIsDirty(IntPtr node);
|
||||
public static extern bool YGNodeIsDirty(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodePrint(IntPtr node, YogaPrintOptions options);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodePrint(YGNodeHandle node, YogaPrintOptions options);
|
||||
|
||||
[DllImport(DllName)]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public static extern bool YGValueIsUndefined(float value);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeCopyStyle(IntPtr dstNode, IntPtr srcNode);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeCopyStyle(YGNodeHandle dstNode, YGNodeHandle srcNode);
|
||||
|
||||
#region YG_NODE_PROPERTY
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeSetContext(IntPtr node, IntPtr context);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern IntPtr YGNodeGetContext(IntPtr node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeSetMeasureFunc(
|
||||
IntPtr node,
|
||||
YGNodeHandle node,
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)] YogaMeasureFunc measureFunc);
|
||||
|
||||
[DllImport(DllName)]
|
||||
[return: MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
public static extern YogaMeasureFunc YGNodeGetMeasureFunc(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeSetBaselineFunc(
|
||||
YGNodeHandle node,
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)] YogaBaselineFunc baselineFunc);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeSetHasNewLayout(IntPtr node, [MarshalAs(UnmanagedType.I1)] bool hasNewLayout);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeSetHasNewLayout(
|
||||
YGNodeHandle node,
|
||||
[MarshalAs(UnmanagedType.I1)] bool hasNewLayout);
|
||||
|
||||
[DllImport(DllName)]
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public static extern bool YGNodeGetHasNewLayout(IntPtr node);
|
||||
public static extern bool YGNodeGetHasNewLayout(YGNodeHandle node);
|
||||
|
||||
#endregion
|
||||
|
||||
#region YG_NODE_STYLE_PROPERTY
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetDirection(IntPtr node, YogaDirection direction);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetDirection(YGNodeHandle node, YogaDirection direction);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern YogaDirection YGNodeStyleGetDirection(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaDirection YGNodeStyleGetDirection(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetFlexDirection(IntPtr node, YogaFlexDirection flexDirection);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetFlexDirection(YGNodeHandle node, YogaFlexDirection flexDirection);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern YogaFlexDirection YGNodeStyleGetFlexDirection(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaFlexDirection YGNodeStyleGetFlexDirection(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetJustifyContent(IntPtr node, YogaJustify justifyContent);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetJustifyContent(YGNodeHandle node, YogaJustify justifyContent);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern YogaJustify YGNodeStyleGetJustifyContent(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaJustify YGNodeStyleGetJustifyContent(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetAlignContent(IntPtr node, YogaAlign alignContent);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetAlignContent(YGNodeHandle node, YogaAlign alignContent);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern YogaAlign YGNodeStyleGetAlignContent(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaAlign YGNodeStyleGetAlignContent(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetAlignItems(IntPtr node, YogaAlign alignItems);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetAlignItems(YGNodeHandle node, YogaAlign alignItems);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern YogaAlign YGNodeStyleGetAlignItems(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaAlign YGNodeStyleGetAlignItems(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetAlignSelf(IntPtr node, YogaAlign alignSelf);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetAlignSelf(YGNodeHandle node, YogaAlign alignSelf);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern YogaAlign YGNodeStyleGetAlignSelf(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaAlign YGNodeStyleGetAlignSelf(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetPositionType(IntPtr node, YogaPositionType positionType);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetPositionType(YGNodeHandle node, YogaPositionType positionType);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern YogaPositionType YGNodeStyleGetPositionType(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaPositionType YGNodeStyleGetPositionType(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetFlexWrap(IntPtr node, YogaWrap flexWrap);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetFlexWrap(YGNodeHandle node, YogaWrap flexWrap);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern YogaWrap YGNodeStyleGetFlexWrap(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaWrap YGNodeStyleGetFlexWrap(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetOverflow(IntPtr node, YogaOverflow flexWrap);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetOverflow(YGNodeHandle node, YogaOverflow flexWrap);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern YogaOverflow YGNodeStyleGetOverflow(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaOverflow YGNodeStyleGetOverflow(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetFlex(IntPtr node, float flex);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetDisplay(YGNodeHandle node, YogaDisplay display);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetFlexGrow(IntPtr node, float flexGrow);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaDisplay YGNodeStyleGetDisplay(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetFlexGrow(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetFlex(YGNodeHandle node, float flex);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetFlexShrink(IntPtr node, float flexShrink);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetFlexGrow(YGNodeHandle node, float flexGrow);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetFlexShrink(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeStyleGetFlexGrow(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetFlexBasis(IntPtr node, float flexBasis);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetFlexShrink(YGNodeHandle node, float flexShrink);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetFlexBasis(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeStyleGetFlexShrink(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetWidth(IntPtr node, float width);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetFlexBasis(YGNodeHandle node, float flexBasis);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetWidth(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetFlexBasisPercent(YGNodeHandle node, float flexBasis);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetHeight(IntPtr node, float height);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetFlexBasisAuto(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetHeight(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaValue YGNodeStyleGetFlexBasis(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetMinWidth(IntPtr node, float minWidth);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetWidth(YGNodeHandle node, float width);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetMinWidth(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetWidthPercent(YGNodeHandle node, float width);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetMinHeight(IntPtr node, float minHeight);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetWidthAuto(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetMinHeight(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaValue YGNodeStyleGetWidth(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetMaxWidth(IntPtr node, float maxWidth);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetHeight(YGNodeHandle node, float height);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetMaxWidth(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetHeightPercent(YGNodeHandle node, float height);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetHeightAuto(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetMaxHeight(IntPtr node, float maxHeight);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaValue YGNodeStyleGetHeight(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetMaxHeight(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMinWidth(YGNodeHandle node, float minWidth);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetAspectRatio(IntPtr node, float aspectRatio);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMinWidthPercent(YGNodeHandle node, float minWidth);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetAspectRatio(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaValue YGNodeStyleGetMinWidth(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMinHeight(YGNodeHandle node, float minHeight);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMinHeightPercent(YGNodeHandle node, float minHeight);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaValue YGNodeStyleGetMinHeight(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMaxWidth(YGNodeHandle node, float maxWidth);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMaxWidthPercent(YGNodeHandle node, float maxWidth);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaValue YGNodeStyleGetMaxWidth(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMaxHeight(YGNodeHandle node, float maxHeight);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMaxHeightPercent(YGNodeHandle node, float maxHeight);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaValue YGNodeStyleGetMaxHeight(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetAspectRatio(YGNodeHandle node, float aspectRatio);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeStyleGetAspectRatio(YGNodeHandle node);
|
||||
|
||||
#endregion
|
||||
|
||||
#region YG_NODE_STYLE_EDGE_PROPERTY
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetPosition(IntPtr node, YogaEdge edge, float position);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetPosition(YGNodeHandle node, YogaEdge edge, float position);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetPosition(IntPtr node, YogaEdge edge);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetPositionPercent(YGNodeHandle node, YogaEdge edge, float position);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetMargin(IntPtr node, YogaEdge edge, float margin);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaValue YGNodeStyleGetPosition(YGNodeHandle node, YogaEdge edge);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetMargin(IntPtr node, YogaEdge edge);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMargin(YGNodeHandle node, YogaEdge edge, float margin);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetPadding(IntPtr node, YogaEdge edge, float padding);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMarginPercent(YGNodeHandle node, YogaEdge edge, float margin);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetPadding(IntPtr node, YogaEdge edge);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetMarginAuto(YGNodeHandle node, YogaEdge edge);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern void YGNodeStyleSetBorder(IntPtr node, YogaEdge edge, float border);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaValue YGNodeStyleGetMargin(YGNodeHandle node, YogaEdge edge);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeStyleGetBorder(IntPtr node, YogaEdge edge);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetPadding(YGNodeHandle node, YogaEdge edge, float padding);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetPaddingPercent(YGNodeHandle node, YogaEdge edge, float padding);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaValue YGNodeStyleGetPadding(YGNodeHandle node, YogaEdge edge);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeStyleSetBorder(YGNodeHandle node, YogaEdge edge, float border);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeStyleGetBorder(YGNodeHandle node, YogaEdge edge);
|
||||
|
||||
#endregion
|
||||
|
||||
#region YG_NODE_LAYOUT_PROPERTY
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeLayoutGetLeft(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeLayoutGetLeft(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeLayoutGetTop(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeLayoutGetTop(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeLayoutGetRight(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeLayoutGetRight(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeLayoutGetBottom(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeLayoutGetBottom(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeLayoutGetWidth(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeLayoutGetWidth(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern float YGNodeLayoutGetHeight(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeLayoutGetHeight(YGNodeHandle node);
|
||||
|
||||
[DllImport(DllName)]
|
||||
public static extern YogaDirection YGNodeLayoutGetDirection(IntPtr node);
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeLayoutGetMargin(YGNodeHandle node, YogaEdge edge);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern float YGNodeLayoutGetPadding(YGNodeHandle node, YogaEdge edge);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern YogaDirection YGNodeLayoutGetDirection(YGNodeHandle node);
|
||||
|
||||
#endregion
|
||||
|
||||
#region IOS
|
||||
|
||||
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr YGNodeGetContext(IntPtr node);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void YGNodeSetContext(IntPtr node, IntPtr managed);
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
}
|
||||
|