Compare commits
3 Commits
dependabot
...
jmaurice-u
Author | SHA1 | Date | |
---|---|---|---|
|
d5d05a40ed | ||
|
b50a7646e2 | ||
|
70369ae5d3 |
@@ -1,3 +1,61 @@
|
|||||||
|
Language: Cpp
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: false
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: Inline
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakBeforeBinaryOperators: false
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 80
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 2000
|
||||||
|
PointerAlignment: Left
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: false
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
Standard: Cpp11
|
||||||
|
UseTab: Never
|
||||||
|
---
|
||||||
|
Language: ObjC
|
||||||
AccessModifierOffset: -1
|
AccessModifierOffset: -1
|
||||||
AlignAfterOpenBracket: AlwaysBreak
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
AlignConsecutiveMacros: false
|
AlignConsecutiveMacros: false
|
||||||
@@ -107,3 +165,4 @@ Standard: Latest
|
|||||||
TabWidth: 8
|
TabWidth: 8
|
||||||
UseCRLF: false
|
UseCRLF: false
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
|
...
|
||||||
|
1
.clang-format-ignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
^lib/.*
|
217
.clang-tidy
@@ -1,217 +0,0 @@
|
|||||||
---
|
|
||||||
InheritParentConfig: true
|
|
||||||
Checks: '>
|
|
||||||
bugprone-argument-comment,
|
|
||||||
bugprone-assert-side-effect,
|
|
||||||
bugprone-bool-pointer-implicit-conversion,
|
|
||||||
bugprone-copy-constructor-init,
|
|
||||||
bugprone-dangling-handle,
|
|
||||||
bugprone-exception-escape,
|
|
||||||
bugprone-fold-init-type,
|
|
||||||
bugprone-forward-declaration-namespace,
|
|
||||||
bugprone-forwarding-reference-overload,
|
|
||||||
bugprone-incorrect-enable-if,
|
|
||||||
bugprone-inaccurate-erase,
|
|
||||||
bugprone-incorrect-roundings,
|
|
||||||
bugprone-infinite-loop,
|
|
||||||
bugprone-integer-division,
|
|
||||||
bugprone-macro-parentheses,
|
|
||||||
bugprone-macro-repeated-side-effects,
|
|
||||||
bugprone-misplaced-operator-in-strlen-in-alloc,
|
|
||||||
bugprone-misplaced-widening-cast,
|
|
||||||
bugprone-move-forwarding-reference,
|
|
||||||
bugprone-multiple-statement-macro,
|
|
||||||
bugprone-optional-value-conversion,
|
|
||||||
bugprone-parent-virtual-call,
|
|
||||||
bugprone-redundant-branch-condition,
|
|
||||||
bugprone-shared-ptr-array-mismatch,
|
|
||||||
bugprone-signed-char-misuse,
|
|
||||||
bugprone-sizeof-container,
|
|
||||||
bugprone-sizeof-expression,
|
|
||||||
bugprone-string-constructor,
|
|
||||||
bugprone-string-integer-assignment,
|
|
||||||
bugprone-string-literal-with-embedded-nul,
|
|
||||||
bugprone-suspicious-enum-usage,
|
|
||||||
bugprone-suspicious-memset-usage,
|
|
||||||
bugprone-suspicious-missing-comma,
|
|
||||||
bugprone-suspicious-semicolon,
|
|
||||||
bugprone-suspicious-string-compare,
|
|
||||||
bugprone-swapped-arguments,
|
|
||||||
bugprone-terminating-continue,
|
|
||||||
bugprone-throw-keyword-missing,
|
|
||||||
bugprone-too-small-loop-variable,
|
|
||||||
bugprone-undefined-memory-manipulation,
|
|
||||||
bugprone-undelegated-constructor,
|
|
||||||
bugprone-unique-ptr-array-mismatch,
|
|
||||||
bugprone-unsafe-functions,
|
|
||||||
bugprone-unused-raii,
|
|
||||||
bugprone-unused-return-value,
|
|
||||||
bugprone-use-after-move,
|
|
||||||
bugprone-virtual-near-miss,
|
|
||||||
clang-analyzer-apiModeling.google.GTest,
|
|
||||||
clang-analyzer-apiModeling.StdCLibraryFunctions,
|
|
||||||
clang-analyzer-apiModeling.TrustNonnull,
|
|
||||||
clang-analyzer-core.builtin.BuiltinFunctions,
|
|
||||||
clang-analyzer-core.builtin.NoReturnFunctions,
|
|
||||||
clang-analyzer-core.CallAndMessage,
|
|
||||||
clang-analyzer-core.DivideZero,
|
|
||||||
clang-analyzer-core.DynamicTypePropagation,
|
|
||||||
clang-analyzer-core.NonnilStringConstants,
|
|
||||||
clang-analyzer-core.NonNullParamChecker,
|
|
||||||
clang-analyzer-core.NullDereference,
|
|
||||||
clang-analyzer-core.StackAddressEscape,
|
|
||||||
clang-analyzer-core.UndefinedBinaryOperatorResult,
|
|
||||||
clang-analyzer-core.uninitialized.ArraySubscript,
|
|
||||||
clang-analyzer-core.uninitialized.Assign,
|
|
||||||
clang-analyzer-core.uninitialized.Branch,
|
|
||||||
clang-analyzer-core.uninitialized.CapturedBlockVariable,
|
|
||||||
clang-analyzer-core.uninitialized.UndefReturn,
|
|
||||||
clang-analyzer-core.VLASize,
|
|
||||||
clang-analyzer-cplusplus.InnerPointer,
|
|
||||||
clang-analyzer-cplusplus.Move,
|
|
||||||
clang-analyzer-cplusplus.NewDelete,
|
|
||||||
clang-analyzer-cplusplus.NewDeleteLeaks,
|
|
||||||
clang-analyzer-cplusplus.SelfAssignment,
|
|
||||||
clang-analyzer-deadcode.DeadStores,
|
|
||||||
clang-analyzer-nullability.NullableDereferenced,
|
|
||||||
clang-analyzer-nullability.NullablePassedToNonnull,
|
|
||||||
clang-analyzer-nullability.NullableReturnedFromNonnull,
|
|
||||||
clang-analyzer-nullability.NullPassedToNonnull,
|
|
||||||
clang-analyzer-nullability.NullReturnedFromNonnull,
|
|
||||||
clang-analyzer-optin.cplusplus.VirtualCall,
|
|
||||||
clang-analyzer-optin.mpi.MPI-Checker,
|
|
||||||
clang-analyzer-optin.performance.GCDAntipattern,
|
|
||||||
clang-analyzer-optin.performance.Padding,
|
|
||||||
clang-analyzer-optin.portability.UnixAPI,
|
|
||||||
clang-analyzer-security.FloatLoopCounter,
|
|
||||||
clang-analyzer-security.insecureAPI.bcmp,
|
|
||||||
clang-analyzer-security.insecureAPI.bcopy,
|
|
||||||
clang-analyzer-security.insecureAPI.bzero,
|
|
||||||
clang-analyzer-security.insecureAPI.getpw,
|
|
||||||
clang-analyzer-security.insecureAPI.gets,
|
|
||||||
clang-analyzer-security.insecureAPI.mkstemp,
|
|
||||||
clang-analyzer-security.insecureAPI.mktemp,
|
|
||||||
clang-analyzer-security.insecureAPI.rand,
|
|
||||||
clang-analyzer-security.insecureAPI.strcpy,
|
|
||||||
clang-analyzer-security.insecureAPI.UncheckedReturn,
|
|
||||||
clang-analyzer-security.insecureAPI.vfork,
|
|
||||||
clang-analyzer-unix.API,
|
|
||||||
clang-analyzer-unix.cstring.BadSizeArg,
|
|
||||||
clang-analyzer-unix.cstring.NullArg,
|
|
||||||
clang-analyzer-unix.Malloc,
|
|
||||||
clang-analyzer-unix.MallocSizeof,
|
|
||||||
clang-analyzer-unix.MismatchedDeallocator,
|
|
||||||
clang-analyzer-unix.Vfork,
|
|
||||||
clang-analyzer-valist.CopyToSelf,
|
|
||||||
clang-analyzer-valist.Uninitialized,
|
|
||||||
clang-analyzer-valist.Unterminated,
|
|
||||||
clang-diagnostic-*,
|
|
||||||
cppcoreguidelines-avoid-const-or-ref-data-members,
|
|
||||||
cppcoreguidelines-avoid-non-const-global-variables,
|
|
||||||
cppcoreguidelines-init-variables,
|
|
||||||
cppcoreguidelines-interfaces-global-init,
|
|
||||||
cppcoreguidelines-macro-usage,
|
|
||||||
cppcoreguidelines-missing-std-forward,
|
|
||||||
cppcoreguidelines-narrowing-conversions,
|
|
||||||
cppcoreguidelines-no-malloc,
|
|
||||||
cppcoreguidelines-prefer-member-initializer,
|
|
||||||
cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
|
||||||
cppcoreguidelines-pro-type-const-cast,
|
|
||||||
cppcoreguidelines-pro-type-cstyle-cast,
|
|
||||||
cppcoreguidelines-pro-type-member-init,
|
|
||||||
cppcoreguidelines-pro-type-reinterpret-cast,
|
|
||||||
cppcoreguidelines-pro-type-union-access,
|
|
||||||
cppcoreguidelines-pro-type-vararg,
|
|
||||||
cppcoreguidelines-slicing,
|
|
||||||
cppcoreguidelines-special-member-functions,
|
|
||||||
facebook-hte-BadEnum,
|
|
||||||
facebook-hte-MissingStatic,
|
|
||||||
google-build-using-namespace,
|
|
||||||
misc-definitions-in-headers,
|
|
||||||
misc-header-include-cycle,
|
|
||||||
misc-misplaced-const,
|
|
||||||
misc-new-delete-overloads,
|
|
||||||
misc-non-copyable-objects,
|
|
||||||
misc-static-assert,
|
|
||||||
misc-throw-by-value-catch-by-reference,
|
|
||||||
misc-unconventional-assign-operator,
|
|
||||||
misc-uniqueptr-reset-release,
|
|
||||||
misc-unused-alias-decls,
|
|
||||||
misc-unused-parameters,
|
|
||||||
misc-unused-using-decls,
|
|
||||||
modernize-avoid-bind,
|
|
||||||
modernize-avoid-c-arrays,
|
|
||||||
modernize-concat-nested-namespaces,
|
|
||||||
modernize-deprecated-headers,
|
|
||||||
modernize-deprecated-ios-base-aliases,
|
|
||||||
modernize-loop-convert,
|
|
||||||
modernize-make-shared,
|
|
||||||
modernize-make-unique,
|
|
||||||
modernize-pass-by-value,
|
|
||||||
modernize-raw-string-literal,
|
|
||||||
modernize-redundant-void-arg,
|
|
||||||
modernize-replace-auto-ptr,
|
|
||||||
modernize-replace-random-shuffle,
|
|
||||||
modernize-return-braced-init-list,
|
|
||||||
modernize-shrink-to-fit,
|
|
||||||
modernize-unary-static-assert,
|
|
||||||
modernize-use-auto,
|
|
||||||
modernize-use-bool-literals,
|
|
||||||
modernize-use-constraints,
|
|
||||||
modernize-use-default-member-init,
|
|
||||||
modernize-use-designated-initializers,
|
|
||||||
modernize-use-emplace,
|
|
||||||
modernize-use-equals-default,
|
|
||||||
modernize-use-equals-delete,
|
|
||||||
modernize-use-noexcept,
|
|
||||||
modernize-use-nullptr,
|
|
||||||
modernize-use-override,
|
|
||||||
modernize-use-starts-ends-with,
|
|
||||||
modernize-use-transparent-functors,
|
|
||||||
modernize-use-using,
|
|
||||||
performance-faster-string-find,
|
|
||||||
performance-for-range-copy,
|
|
||||||
performance-implicit-conversion-in-loop,
|
|
||||||
performance-inefficient-algorithm,
|
|
||||||
performance-inefficient-string-concatenation,
|
|
||||||
performance-inefficient-vector-operation,
|
|
||||||
performance-move-const-arg,
|
|
||||||
performance-move-constructor-init,
|
|
||||||
performance-noexcept-move-constructor,
|
|
||||||
performance-type-promotion-in-math-fn,
|
|
||||||
performance-unnecessary-copy-initialization,
|
|
||||||
performance-unnecessary-value-param,
|
|
||||||
readability-avoid-const-params-in-decls,
|
|
||||||
readability-braces-around-statements,
|
|
||||||
readability-const-return-type,
|
|
||||||
readability-container-size-empty,
|
|
||||||
readability-delete-null-pointer,
|
|
||||||
readability-deleted-default,
|
|
||||||
readability-implicit-bool-conversion,
|
|
||||||
readability-inconsistent-declaration-parameter-name,
|
|
||||||
readability-isolate-declaration,
|
|
||||||
readability-misplaced-array-index,
|
|
||||||
readability-named-parameter,
|
|
||||||
readability-non-const-parameter,
|
|
||||||
readability-redundant-control-flow,
|
|
||||||
readability-redundant-declaration,
|
|
||||||
readability-redundant-function-ptr-dereference,
|
|
||||||
readability-redundant-preprocessor,
|
|
||||||
readability-redundant-smartptr-get,
|
|
||||||
readability-redundant-string-cstr,
|
|
||||||
readability-redundant-string-init,
|
|
||||||
readability-simplify-boolean-expr,
|
|
||||||
readability-simplify-subscript-expr,
|
|
||||||
readability-static-accessed-through-instance,
|
|
||||||
readability-static-definition-in-anonymous-namespace,
|
|
||||||
readability-string-compare,
|
|
||||||
readability-uniqueptr-delete-release,
|
|
||||||
'
|
|
||||||
|
|
||||||
CheckOptions:
|
|
||||||
- key: performance-unnecessary-value-param.AllowedTypes
|
|
||||||
value: '[Pp]ointer$;[Pp]tr$;[Rr]ef(erence)?$;'
|
|
||||||
- key: performance-unnecessary-copy-initialization.AllowedTypes
|
|
||||||
value: '[Pp]ointer$;[Pp]tr$;[Rr]ef(erence)?$'
|
|
||||||
|
|
||||||
...
|
|
@@ -1,84 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*
|
|
||||||
* @format
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
ignorePatterns: ['**/binaries/**', '**/build/**', '**/generated/**'],
|
|
||||||
overrides: [
|
|
||||||
// Catch-all
|
|
||||||
{
|
|
||||||
files: ['**/*.?(m|c){j,t}s?(x)'],
|
|
||||||
extends: ['eslint:recommended', 'plugin:prettier/recommended'],
|
|
||||||
plugins: ['prettier'],
|
|
||||||
rules: {
|
|
||||||
'no-unused-vars': ['error', {argsIgnorePattern: '^_'}],
|
|
||||||
'no-var': 'error',
|
|
||||||
'prefer-arrow-callback': 'error',
|
|
||||||
'prefer-const': 'error',
|
|
||||||
'prefer-object-spread': 'error',
|
|
||||||
'prefer-spread': 'error',
|
|
||||||
'require-await': 'error',
|
|
||||||
},
|
|
||||||
env: {
|
|
||||||
es2020: true,
|
|
||||||
'shared-node-browser': true,
|
|
||||||
},
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 'latest',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// ES Modules
|
|
||||||
{
|
|
||||||
files: ['**/*.?(m){j,t}s?(x)'],
|
|
||||||
parserOptions: {
|
|
||||||
sourceType: 'module',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// CommonJS Modules
|
|
||||||
{
|
|
||||||
files: ['**/*.c{j,t}s?(x)'],
|
|
||||||
env: {
|
|
||||||
commonjs: true,
|
|
||||||
},
|
|
||||||
parserOptions: {
|
|
||||||
sourceType: 'commonjs',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// TypeScript
|
|
||||||
{
|
|
||||||
files: ['**/*.?(m|c)ts?(x)'],
|
|
||||||
extends: ['plugin:@typescript-eslint/recommended'],
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
parserOptions: {
|
|
||||||
project: true,
|
|
||||||
},
|
|
||||||
plugins: ['@typescript-eslint'],
|
|
||||||
rules: {
|
|
||||||
'@typescript-eslint/ban-ts-comment': 'off',
|
|
||||||
'@typescript-eslint/no-unused-vars': [
|
|
||||||
'error',
|
|
||||||
{argsIgnorePattern: '^_'},
|
|
||||||
],
|
|
||||||
'@typescript-eslint/no-var-requires': 'off',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Node
|
|
||||||
{
|
|
||||||
files: ['**/.*rc.(c){j,t}s', '**/*.config.?(c){j,t}s'],
|
|
||||||
env: {
|
|
||||||
node: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Jest
|
|
||||||
{
|
|
||||||
files: ['**/tests/**'],
|
|
||||||
extends: ['plugin:jest/recommended'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
10
.github/actions/cache-emsdk/action.yml
vendored
@@ -1,10 +0,0 @@
|
|||||||
name: Cache the installed copy of emsdk and its build artifacts
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- name: Cache emsdk
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: javascript/.emsdk
|
|
||||||
key: emsdk-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('yarn.lock', 'javascript/package.json', 'javascript/just.config.cjs')}}
|
|
23
.github/actions/install-emsdk/action.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
name: Install emsdk (including emcc)
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: EMCC Version to install
|
||||||
|
required: false
|
||||||
|
default: 3.1.28
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Clone emsdk repo
|
||||||
|
working-directory: ${{ runner.temp }}
|
||||||
|
shell: bash
|
||||||
|
run: git clone https://github.com/emscripten-core/emsdk.git
|
||||||
|
|
||||||
|
- name: emdsk install
|
||||||
|
working-directory: ${{ runner.temp }}/emsdk
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
./emsdk install ${{ inputs.version }}
|
||||||
|
./emsdk activate ${{ inputs.version }}
|
||||||
|
echo $RUNNER_TEMP/emsdk >> $GITHUB_PATH
|
||||||
|
echo $RUNNER_TEMP/emsdk/upstream/emscripten >> $GITHUB_PATH
|
8
.github/actions/setup-android/action.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Setup Android environment
|
name: Setup Android envirionment
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
@@ -6,7 +6,5 @@ runs:
|
|||||||
- name: Select Java Version
|
- name: Select Java Version
|
||||||
uses: actions/setup-java@v2
|
uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
distribution: zulu
|
distribution: temurin
|
||||||
java-version: 17
|
java-version: 11
|
||||||
- name: Configure Gradle Caches
|
|
||||||
uses: gradle/gradle-build-action@v2
|
|
||||||
|
4
.github/actions/setup-apple/action.yml
vendored
@@ -7,7 +7,3 @@ runs:
|
|||||||
- name: Install Cocoapods
|
- name: Install Cocoapods
|
||||||
shell: bash
|
shell: bash
|
||||||
run: sudo gem install cocoapods
|
run: sudo gem install cocoapods
|
||||||
|
|
||||||
- uses: maxim-lobanov/setup-xcode@v1
|
|
||||||
with:
|
|
||||||
xcode-version: 14.3.1
|
|
||||||
|
21
.github/actions/setup-cpp/action.yml
vendored
@@ -1,9 +1,4 @@
|
|||||||
name: Setup C++ envirionment
|
name: Setup C++ envirionment
|
||||||
inputs:
|
|
||||||
toolchain:
|
|
||||||
description: Compiler toolchain to use (Clang, GCC, or MSVC)
|
|
||||||
required: false
|
|
||||||
default: 'Clang'
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
@@ -12,22 +7,6 @@ runs:
|
|||||||
if: ${{ runner.os != 'Windows' }}
|
if: ${{ runner.os != 'Windows' }}
|
||||||
uses: ./.github/actions/install-ninja
|
uses: ./.github/actions/install-ninja
|
||||||
|
|
||||||
- name: Set Clang as compiler
|
|
||||||
if: ${{ inputs.toolchain == 'Clang' }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "CC=/usr/bin/clang" >> $GITHUB_ENV
|
|
||||||
echo "CXX=/usr/bin/clang++" >> $GITHUB_ENV
|
|
||||||
echo "CXXFLAGS=-stdlib=libc++" >> $GITHUB_ENV
|
|
||||||
echo "LDFLAGS=-stdlib=libc++" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set GCC as compiler
|
|
||||||
if: ${{ inputs.toolchain == 'GCC' }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "CC=/usr/bin/gcc" >> $GITHUB_ENV
|
|
||||||
echo "CXX=/usr/bin/g++" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Setup VS Developer Command Prompt
|
- name: Setup VS Developer Command Prompt
|
||||||
if: ${{ runner.os == 'Windows' }}
|
if: ${{ runner.os == 'Windows' }}
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
18
.github/actions/setup-js/action.yml
vendored
@@ -3,16 +3,18 @@ name: Setup JavaScript envirionment
|
|||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- name: Setup Node environment
|
- name: Install Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 18.x
|
||||||
cache: yarn
|
|
||||||
cache-dependency-path: yarn.lock
|
- name: Install emsdk
|
||||||
env:
|
uses: ./.github/actions/install-emsdk
|
||||||
# https://github.com/actions/setup-node/issues/317
|
|
||||||
FORCE_COLOR: 0
|
- name: Install Ninja
|
||||||
|
uses: ./.github/actions/install-ninja
|
||||||
|
|
||||||
- name: yarn install
|
- name: yarn install
|
||||||
shell: bash
|
shell: bash
|
||||||
run: yarn install --frozen-lockfile
|
run: yarn install --frozen-lockfile
|
||||||
|
working-directory: javascript
|
||||||
|
18
.github/actions/setup-website/action.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
name: Setup Website envirionment
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
# TODO: Update to latest when website is moved to the workspace version of
|
||||||
|
# yoga-layout
|
||||||
|
- name: Install Node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 12.x
|
||||||
|
|
||||||
|
# TODO: the website should be in a yarn workspace with the library, but the
|
||||||
|
# current version of gatsby is incompatible with hoisting.
|
||||||
|
- name: yarn install
|
||||||
|
shell: bash
|
||||||
|
run: yarn install --frozen-lockfile
|
||||||
|
working-directory: website
|
38
.github/workflows/publish-android-release.yml
vendored
@@ -1,38 +0,0 @@
|
|||||||
name: Publish Android Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '*'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
name: Publish to Maven Central
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
uses: ./.github/actions/setup-android
|
|
||||||
|
|
||||||
- name: Publish to Maven Local
|
|
||||||
run: ./gradlew publishToMavenLocal
|
|
||||||
env:
|
|
||||||
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
|
|
||||||
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
|
|
||||||
|
|
||||||
- name: Upload Build Artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: 'snapshot-artifacts'
|
|
||||||
path: '~/.m2/repository/'
|
|
||||||
|
|
||||||
- name: Publish to the Maven Central
|
|
||||||
run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository
|
|
||||||
env:
|
|
||||||
ORG_GRADLE_PROJECT_SONATYPE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_USERNAME }}
|
|
||||||
ORG_GRADLE_PROJECT_SONATYPE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_PASSWORD }}
|
|
||||||
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
|
|
||||||
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
|
|
36
.github/workflows/publish-android-snashot.yml
vendored
@@ -1,36 +0,0 @@
|
|||||||
name: Publish Android Snapshot
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
name: Publish Snapshot
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
uses: ./.github/actions/setup-android
|
|
||||||
|
|
||||||
- name: Publish to Maven Local
|
|
||||||
run: ./gradlew publishToMavenLocal
|
|
||||||
env:
|
|
||||||
ORG_GRADLE_PROJECT_USE_SNAPSHOT: true
|
|
||||||
|
|
||||||
- name: Upload Build Artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: 'snapshot-artifacts'
|
|
||||||
path: '~/.m2/repository/'
|
|
||||||
|
|
||||||
- name: Publish to the Snapshot Repository
|
|
||||||
run: ./gradlew publishToSonatype
|
|
||||||
env:
|
|
||||||
ORG_GRADLE_PROJECT_SONATYPE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_USERNAME }}
|
|
||||||
ORG_GRADLE_PROJECT_SONATYPE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_PASSWORD }}
|
|
||||||
ORG_GRADLE_PROJECT_USE_SNAPSHOT: true
|
|
29
.github/workflows/publish-android.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
name: Android
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
name: Publish to Maven Central
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup
|
||||||
|
uses: ./.github/actions/setup-android
|
||||||
|
|
||||||
|
- name: Publish and release
|
||||||
|
run: |
|
||||||
|
./gradlew :yoga:assembleRelease publish --info
|
||||||
|
./gradlew closeAndReleaseRepository
|
||||||
|
env:
|
||||||
|
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_NEXUS_USERNAME }}
|
||||||
|
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_NEXUS_PASSWORD }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_KEY_CONTENTS }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_KEY_ID }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }}
|
23
.github/workflows/publish-cocoapods-release.yml
vendored
@@ -1,23 +0,0 @@
|
|||||||
name: Publish CocoaPods Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '*'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
name: Publish to CocoaPods trunk
|
|
||||||
runs-on: macos-13
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
uses: ./.github/actions/setup-apple
|
|
||||||
|
|
||||||
- name: Publish Yoga
|
|
||||||
run: pod trunk push Yoga.podspec
|
|
||||||
env:
|
|
||||||
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
|
|
25
.github/workflows/publish-npm-release.yml
vendored
@@ -1,25 +0,0 @@
|
|||||||
name: Publish NPM Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '*'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
name: Publish to npmjs registry
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
uses: ./.github/actions/setup-js
|
|
||||||
|
|
||||||
- name: Store auth token in config file
|
|
||||||
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
|
|
||||||
|
|
||||||
- name: yarn publish
|
|
||||||
run: yarn publish
|
|
||||||
working-directory: javascript
|
|
32
.github/workflows/publish-website.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name: Website
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
name: Publish to GitHub Pages
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup
|
||||||
|
uses: ./.github/actions/setup-website
|
||||||
|
|
||||||
|
- name: yarn build
|
||||||
|
run: yarn build
|
||||||
|
working-directory: website
|
||||||
|
|
||||||
|
- uses: peaceiris/actions-gh-pages@v3
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_branch: gh-pages
|
||||||
|
publish_dir: website/public
|
||||||
|
cname: yogalayout.com
|
||||||
|
keep_files: true
|
||||||
|
user_name: 'Yoga-bot'
|
||||||
|
user_email: 'yogabot@fb.com'
|
3
.github/workflows/validate-android.yml
vendored
@@ -1,11 +1,10 @@
|
|||||||
name: Validate Android
|
name: Android
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- 'release-*'
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
42
.github/workflows/validate-apple.yml
vendored
@@ -1,17 +1,16 @@
|
|||||||
name: Validate Apple
|
name: Apple
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- 'release-*'
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint-pods:
|
lint-pods:
|
||||||
name: Build [CocoaPods]
|
name: Lint
|
||||||
runs-on: macos-13
|
runs-on: macos-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -19,12 +18,16 @@ jobs:
|
|||||||
- name: Setup
|
- name: Setup
|
||||||
uses: ./.github/actions/setup-apple
|
uses: ./.github/actions/setup-apple
|
||||||
|
|
||||||
- name: pod lib lint
|
- name: pod spec lint
|
||||||
run: pod lib lint --verbose --include-podspecs=**/*.podspec
|
run: pod spec lint --verbose
|
||||||
|
continue-on-error: true # Apple Build is Broken
|
||||||
|
|
||||||
test:
|
build-sample:
|
||||||
name: Build [SwiftPM]
|
name: Build [${{ matrix.mode }}]
|
||||||
runs-on: macos-13
|
runs-on: macos-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
mode: [Debug, Release]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -32,8 +35,21 @@ jobs:
|
|||||||
- name: Setup
|
- name: Setup
|
||||||
uses: ./.github/actions/setup-apple
|
uses: ./.github/actions/setup-apple
|
||||||
|
|
||||||
- name: Build Debug
|
- name: pod install
|
||||||
run: swift build -c debug
|
run: pod install
|
||||||
|
working-directory: ./YogaKit/YogaKitSample
|
||||||
|
continue-on-error: true # Apple Build is Broken
|
||||||
|
|
||||||
- name: Build Release
|
# TODO: xcodebuild
|
||||||
run: swift build -c release
|
|
||||||
|
clang-format:
|
||||||
|
name: Format
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: clang-format
|
||||||
|
uses: ./.github/actions/clang-format
|
||||||
|
with:
|
||||||
|
directory: ./YogaKit
|
||||||
|
69
.github/workflows/validate-cpp.yml
vendored
@@ -1,11 +1,10 @@
|
|||||||
name: Validate C++
|
name: C++
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- 'release-*'
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@@ -13,91 +12,45 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: Build and Test [${{ matrix.toolchain }}][${{ matrix.mode }}]
|
name: Build and Test [${{ matrix.os }}][${{ matrix.mode }}]
|
||||||
runs-on: ${{ (matrix.toolchain == 'MSVC') && 'windows-latest' || 'ubuntu-latest' }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
mode: [Debug, Release]
|
mode: [Debug, Release]
|
||||||
toolchain: [Clang, GCC] # TODO: fix issues building GTest Binary with MSVC in GitHub Actions
|
os: [ubuntu-latest] # TODO: fix issues building GTest Binary with MSVC in GitHub Actions
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup
|
- name: Setup
|
||||||
uses: ./.github/actions/setup-cpp
|
uses: ./.github/actions/setup-cpp
|
||||||
with:
|
|
||||||
toolchain: ${{ matrix.toolchain }}
|
|
||||||
|
|
||||||
- name: Unit tests
|
- name: Unit tests
|
||||||
run: ./unit_tests ${{ matrix.mode }}
|
run: ./unit_tests ${{ matrix.mode }}
|
||||||
|
|
||||||
|
|
||||||
build_fuzzers:
|
|
||||||
name: Build fuzzers [${{ matrix.toolchain }}][${{ matrix.mode }}]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
mode: [Debug, Release]
|
|
||||||
toolchain: [Clang]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
uses: ./.github/actions/setup-cpp
|
|
||||||
with:
|
|
||||||
toolchain: ${{ matrix.toolchain }}
|
|
||||||
|
|
||||||
- name: Unit tests
|
|
||||||
run: ./build_fuzz_tests ${{ matrix.mode }}
|
|
||||||
|
|
||||||
benchmark:
|
benchmark:
|
||||||
name: Benchmark [${{ matrix.toolchain }}]
|
name: Benchmark [${{ matrix.os }}]
|
||||||
runs-on: ${{ (matrix.toolchain == 'MSVC') && 'windows-latest' || 'ubuntu-latest' }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
toolchain: [Clang, GCC, MSVC]
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup
|
- name: Setup
|
||||||
uses: ./.github/actions/setup-cpp
|
uses: ./.github/actions/setup-cpp
|
||||||
with:
|
|
||||||
toolchain: ${{ matrix.toolchain }}
|
|
||||||
|
|
||||||
- name: Build and run benchmark
|
- name: Build benchmark
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B build -G Ninja -D CMAKE_BUILD_TYPE=Release
|
cmake -S . -B build -G Ninja -D CMAKE_BUILD_TYPE=Release
|
||||||
cmake --build build
|
cmake --build build
|
||||||
./build/benchmark ./captures
|
|
||||||
working-directory: benchmark
|
working-directory: benchmark
|
||||||
|
|
||||||
- name: Build and run benchmarklegacy
|
- name: Run benchmark
|
||||||
run: ./build/benchmarklegacy
|
run: ./build/benchmark
|
||||||
working-directory: benchmark
|
working-directory: benchmark
|
||||||
|
|
||||||
capture:
|
|
||||||
name: Capture [${{ matrix.toolchain }}]
|
|
||||||
runs-on: ${{ (matrix.toolchain == 'MSVC') && 'windows-latest' || 'ubuntu-latest' }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
toolchain: [Clang, GCC, MSVC]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
uses: ./.github/actions/setup-cpp
|
|
||||||
with:
|
|
||||||
toolchain: ${{ matrix.toolchain }}
|
|
||||||
|
|
||||||
- name: Build capture
|
|
||||||
run: |
|
|
||||||
cmake -S . -B build -G Ninja -D CMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build build
|
|
||||||
working-directory: capture
|
|
||||||
|
|
||||||
clang-format:
|
clang-format:
|
||||||
name: Format
|
name: Format
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -107,3 +60,5 @@ jobs:
|
|||||||
|
|
||||||
- name: clang-format
|
- name: clang-format
|
||||||
uses: ./.github/actions/clang-format
|
uses: ./.github/actions/clang-format
|
||||||
|
with:
|
||||||
|
directory: ./yoga
|
||||||
|
54
.github/workflows/validate-js.yml
vendored
@@ -1,11 +1,10 @@
|
|||||||
name: Validate JavaScript
|
name: JavaScript
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- 'release-*'
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@@ -24,9 +23,6 @@ jobs:
|
|||||||
- name: Setup
|
- name: Setup
|
||||||
uses: ./.github/actions/setup-js
|
uses: ./.github/actions/setup-js
|
||||||
|
|
||||||
- name: Restore emsdk
|
|
||||||
uses: ./.github/actions/cache-emsdk
|
|
||||||
|
|
||||||
- name: yarn benchmark
|
- name: yarn benchmark
|
||||||
run: yarn benchmark
|
run: yarn benchmark
|
||||||
working-directory: javascript
|
working-directory: javascript
|
||||||
@@ -43,11 +39,8 @@ jobs:
|
|||||||
- name: Setup
|
- name: Setup
|
||||||
uses: ./.github/actions/setup-js
|
uses: ./.github/actions/setup-js
|
||||||
|
|
||||||
- name: Restore emsdk
|
|
||||||
uses: ./.github/actions/cache-emsdk
|
|
||||||
|
|
||||||
- name: yarn build
|
- name: yarn build
|
||||||
run: yarn build --verbose
|
run: yarn build
|
||||||
working-directory: javascript
|
working-directory: javascript
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@@ -62,55 +55,20 @@ jobs:
|
|||||||
- name: Setup
|
- name: Setup
|
||||||
uses: ./.github/actions/setup-js
|
uses: ./.github/actions/setup-js
|
||||||
|
|
||||||
- name: Restore emsdk
|
|
||||||
uses: ./.github/actions/cache-emsdk
|
|
||||||
|
|
||||||
- name: yarn test
|
- name: yarn test
|
||||||
run: yarn test
|
run: yarn test
|
||||||
working-directory: javascript
|
working-directory: javascript
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
name: ESLint (All Packages)
|
name: Lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup
|
- name: yarn install
|
||||||
uses: ./.github/actions/setup-js
|
run: yarn install --frozen-lockfile
|
||||||
|
working-directory: javascript
|
||||||
|
|
||||||
- name: yarn lint
|
- name: yarn lint
|
||||||
run: yarn lint
|
run: yarn lint
|
||||||
|
|
||||||
typecheck:
|
|
||||||
name: Typecheck
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
uses: ./.github/actions/setup-js
|
|
||||||
|
|
||||||
- name: yarn tsc
|
|
||||||
run: yarn tsc
|
|
||||||
working-directory: javascript
|
working-directory: javascript
|
||||||
|
|
||||||
pack:
|
|
||||||
name: Pack
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
uses: ./.github/actions/setup-js
|
|
||||||
|
|
||||||
- name: Restore emsdk
|
|
||||||
uses: ./.github/actions/cache-emsdk
|
|
||||||
|
|
||||||
- name: yarn pack
|
|
||||||
run: yarn pack --filename yoga-layout.tar.gz
|
|
||||||
working-directory: javascript
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: npm-package
|
|
||||||
path: javascript/yoga-layout.tar.gz
|
|
||||||
|
21
.github/workflows/validate-python.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
name: Python
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
format:
|
||||||
|
name: Format
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: black --check
|
||||||
|
uses: ./.github/actions/black
|
||||||
|
with:
|
||||||
|
directory: ${{ github.workspace }}
|
32
.github/workflows/validate-tests.yml
vendored
@@ -1,32 +0,0 @@
|
|||||||
name: Validate Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
validate:
|
|
||||||
name: Validate
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup JS
|
|
||||||
uses: ./.github/actions/setup-js
|
|
||||||
|
|
||||||
- name: yarn gentest-validate
|
|
||||||
run: yarn gentest-validate
|
|
||||||
|
|
||||||
- name: yarn gentest
|
|
||||||
run: yarn gentest -h
|
|
||||||
|
|
||||||
- name: Check for modified tests
|
|
||||||
run: |
|
|
||||||
if [[ -n $(git status -s) ]]; then
|
|
||||||
git status -s
|
|
||||||
echo "yarn gentest modified these tests. Please run yarn gentest to resolve."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
29
.github/workflows/validate-website.yml
vendored
@@ -1,42 +1,23 @@
|
|||||||
name: Validate Website
|
name: Website
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_next:
|
build:
|
||||||
name: Build
|
name: Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup
|
- name: Setup
|
||||||
uses: ./.github/actions/setup-js
|
uses: ./.github/actions/setup-website
|
||||||
|
|
||||||
- name: Restore emsdk
|
- name: yarn build
|
||||||
uses: ./.github/actions/cache-emsdk
|
|
||||||
|
|
||||||
- name: Build Website
|
|
||||||
run: yarn build
|
run: yarn build
|
||||||
working-directory: website
|
working-directory: website
|
||||||
|
|
||||||
typecheck:
|
|
||||||
name: Typecheck [Docusaurus]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
uses: ./.github/actions/setup-js
|
|
||||||
|
|
||||||
- name: yarn tsc
|
|
||||||
run: yarn tsc
|
|
||||||
working-directory: website
|
|
||||||
|
5
.gitignore
vendored
@@ -6,7 +6,6 @@
|
|||||||
/.buckd
|
/.buckd
|
||||||
/gentest/test.html
|
/gentest/test.html
|
||||||
.buck-java11
|
.buck-java11
|
||||||
node_modules
|
|
||||||
|
|
||||||
# Jekyll
|
# Jekyll
|
||||||
/.sass-cache/
|
/.sass-cache/
|
||||||
@@ -65,11 +64,7 @@ Carthage/Build
|
|||||||
|
|
||||||
# Gradle
|
# Gradle
|
||||||
.gradle
|
.gradle
|
||||||
local.properties
|
|
||||||
|
|
||||||
# NDK/CMake
|
# NDK/CMake
|
||||||
.cxx
|
.cxx
|
||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
|
|
||||||
# Docusarus build
|
|
||||||
.docusaurus
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
**/binaries/**
|
|
||||||
**/build/**
|
|
||||||
**/generated/**
|
|
@@ -3,7 +3,7 @@
|
|||||||
# This source code is licensed under the MIT license found in the
|
# This source code is licensed under the MIT license found in the
|
||||||
# LICENSE file in the root directory of this source tree.
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.13...3.26)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
project(yoga-all)
|
project(yoga-all)
|
||||||
set(CMAKE_VERBOSE_MAKEFILE on)
|
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||||
|
|
||||||
@@ -12,12 +12,6 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/project-defaults.cmake)
|
|||||||
add_subdirectory(yoga)
|
add_subdirectory(yoga)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
|
||||||
option(BUILD_FUZZ_TESTS "Build fuzz tests" OFF)
|
|
||||||
|
|
||||||
if ('${CMAKE_CXX_COMPILER_ID}' MATCHES 'Clang' AND BUILD_FUZZ_TESTS)
|
|
||||||
add_subdirectory(fuzz)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# cmake install config
|
# cmake install config
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
|
@@ -1,32 +0,0 @@
|
|||||||
// swift-tools-version:5.0
|
|
||||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
|
||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
import PackageDescription
|
|
||||||
|
|
||||||
let package = Package(
|
|
||||||
name: "yoga",
|
|
||||||
products: [
|
|
||||||
.library(name: "yoga", targets: [ "core" ])
|
|
||||||
],
|
|
||||||
targets: [
|
|
||||||
.target(
|
|
||||||
name: "core",
|
|
||||||
path: ".",
|
|
||||||
sources: [
|
|
||||||
"yoga"
|
|
||||||
],
|
|
||||||
publicHeadersPath: ".",
|
|
||||||
cxxSettings: [
|
|
||||||
.headerSearchPath(".")
|
|
||||||
]
|
|
||||||
)
|
|
||||||
],
|
|
||||||
cxxLanguageStandard: CXXLanguageStandard(rawValue: "c++20")
|
|
||||||
)
|
|
13
README.md
@@ -1,10 +1,10 @@
|
|||||||
# Yoga [](http://cocoapods.org/pods/Yoga) [](https://www.npmjs.com/package/yoga-layout) [](https://search.maven.org/artifact/com.facebook.yoga/yoga) 
|
# Yoga [](https://opensource.fb.com/support-ukraine) [](http://cocoapods.org/pods/YogaKit) [](https://www.npmjs.com/package/yoga-layout) [](https://search.maven.org/artifact/com.facebook.yoga/yoga)
|
||||||
|
|
||||||
Yoga is an embeddable and performant flexbox layout engine with bindings for multiple languages.
|
Yoga is an embeddable and performant flexbox layout engine with bindings for multiple languages.
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
Yoga's main implementation targets C++ 20 with accompanying build logic in CMake. A wrapper is provided to build the main library and run unit tests.
|
## Building
|
||||||
|
Yoga's main implementation targets C++ 14 with accompanying build logic in CMake. A wrapper is provided to build the main library and run unit tests.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./unit_tests <Debug|Release>
|
./unit_tests <Debug|Release>
|
||||||
@@ -14,6 +14,8 @@ While not required, this script will use [ninja](https://ninja-build.org/) if it
|
|||||||
|
|
||||||
Yoga is additionally part of the [vcpkg](https://github.com/Microsoft/vcpkg/) collection of ports maintained by Microsoft and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
Yoga is additionally part of the [vcpkg](https://github.com/Microsoft/vcpkg/) collection of ports maintained by Microsoft and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Adding Tests
|
## Adding Tests
|
||||||
|
|
||||||
Many of Yoga's tests are automatically generated, using HTML fixtures describing node structure. These are rendered in Chrome to generate an expected layout result for the tree. New fixtures can be added to `gentest/fixtures`.
|
Many of Yoga's tests are automatically generated, using HTML fixtures describing node structure. These are rendered in Chrome to generate an expected layout result for the tree. New fixtures can be added to `gentest/fixtures`.
|
||||||
@@ -25,10 +27,9 @@ Many of Yoga's tests are automatically generated, using HTML fixtures describing
|
|||||||
```
|
```
|
||||||
|
|
||||||
To generate new tests from added fixtures:
|
To generate new tests from added fixtures:
|
||||||
|
1. Run `bundle install` in the `gentest` directory to install dependencies of the test generator.
|
||||||
|
2. Run `ruby gentest.rb` in the `gentest` directory.
|
||||||
|
|
||||||
1. Ensure you have [yarn classic](https://classic.yarnpkg.com) installed.
|
|
||||||
2. Run `yarn install` to install dependencies for the test generator.
|
|
||||||
3. Run `yarn gentest` in the `yoga` directory.
|
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
|
35
Yoga.podspec
@@ -6,45 +6,34 @@
|
|||||||
|
|
||||||
Pod::Spec.new do |spec|
|
Pod::Spec.new do |spec|
|
||||||
spec.name = 'Yoga'
|
spec.name = 'Yoga'
|
||||||
spec.version = '0.0.0'
|
spec.version = '1.14.0'
|
||||||
spec.license = { :type => 'MIT', :file => "LICENSE" }
|
spec.license = { :type => 'MIT', :file => "LICENSE" }
|
||||||
spec.homepage = 'https://yogalayout.dev/'
|
spec.homepage = 'https://yogalayout.com/'
|
||||||
spec.documentation_url = 'https://yogalayout.dev/docs'
|
spec.documentation_url = 'https://yogalayout.com/docs'
|
||||||
|
|
||||||
spec.summary = 'An embeddable and performant flexbox layout engine with bindings for multiple languages'
|
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 = {'Meta Open Source' => 'opensource@meta.com'}
|
spec.authors = 'Facebook'
|
||||||
spec.source = {
|
spec.source = {
|
||||||
:git => 'https://github.com/facebook/yoga.git',
|
:git => 'https://github.com/facebook/yoga.git',
|
||||||
:tag => "v#{spec.version.to_s}",
|
:tag => spec.version.to_s,
|
||||||
}
|
}
|
||||||
|
spec.platforms = { :ios => "8.0", :osx => "10.7", :tvos => "10.0", :watchos => "2.0" }
|
||||||
spec.ios.deployment_target = "13.4"
|
|
||||||
|
|
||||||
spec.module_name = 'yoga'
|
spec.module_name = 'yoga'
|
||||||
spec.requires_arc = false
|
spec.requires_arc = false
|
||||||
spec.pod_target_xcconfig = {
|
spec.pod_target_xcconfig = {
|
||||||
'DEFINES_MODULE' => 'YES',
|
'DEFINES_MODULE' => 'YES'
|
||||||
'HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)"',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spec.compiler_flags = [
|
spec.compiler_flags = [
|
||||||
'-fno-omit-frame-pointer',
|
'-fno-omit-frame-pointer',
|
||||||
'-fexceptions',
|
'-fexceptions',
|
||||||
'-Wall',
|
'-Wall',
|
||||||
'-Werror',
|
'-Werror',
|
||||||
'-std=c++20',
|
'-std=c++14',
|
||||||
'-fPIC'
|
'-fPIC'
|
||||||
]
|
]
|
||||||
|
spec.source_files = 'yoga/**/*.{c,h,cpp}'
|
||||||
|
spec.public_header_files = 'yoga/*.h'
|
||||||
|
|
||||||
spec.swift_version = '5.1'
|
|
||||||
spec.source_files = 'yoga/**/*.{h,cpp}'
|
|
||||||
spec.header_mappings_dir = 'yoga'
|
|
||||||
|
|
||||||
public_header_files = 'yoga/*.h'
|
|
||||||
spec.public_header_files = public_header_files
|
|
||||||
|
|
||||||
all_header_files = 'yoga/**/*.h'
|
|
||||||
spec.private_header_files = Dir.glob(all_header_files) - Dir.glob(public_header_files)
|
|
||||||
spec.preserve_paths = [all_header_files]
|
|
||||||
end
|
end
|
||||||
|
39
YogaKit.podspec
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
podspec = Pod::Spec.new do |spec|
|
||||||
|
spec.name = 'YogaKit'
|
||||||
|
spec.version = '1.18.1'
|
||||||
|
spec.license = { :type => 'MIT', :file => "LICENSE" }
|
||||||
|
spec.homepage = 'https://facebook.github.io/yoga/'
|
||||||
|
spec.documentation_url = 'https://facebook.github.io/yoga/docs/'
|
||||||
|
|
||||||
|
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 => "1.18.0",
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.platform = :ios
|
||||||
|
spec.ios.deployment_target = '8.0'
|
||||||
|
spec.ios.frameworks = 'UIKit'
|
||||||
|
spec.module_name = 'YogaKit'
|
||||||
|
spec.dependency 'Yoga', '~> 1.14'
|
||||||
|
# Fixes the bug related the xcode 11 not able to find swift related frameworks.
|
||||||
|
# https://github.com/Carthage/Carthage/issues/2825
|
||||||
|
# https://twitter.com/krzyzanowskim/status/1151549874653081601?s=21
|
||||||
|
spec.pod_target_xcconfig = {"LD_VERIFY_BITCODE": "NO"}
|
||||||
|
spec.source_files = 'YogaKit/Source/*.{h,m,swift}'
|
||||||
|
spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h'
|
||||||
|
spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h'
|
||||||
|
spec.swift_version = '5.1'
|
||||||
|
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
|
21
YogaKit/README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# 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.7'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
We have a sample project. To try it out, clone this repo and open `YogaKitSample.xcodeproj` in the [YogaKitSample](https://github.com/facebook/yoga/tree/main/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.md](https://github.com/facebook/yoga/blob/main/CONTRIBUTING.md) file for how to help out.
|
37
YogaKit/Source/UIView+Yoga.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import "YGLayout.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
typedef void (^YGLayoutConfigurationBlock)(YGLayout* layout);
|
||||||
|
|
||||||
|
@interface UIView (Yoga)
|
||||||
|
|
||||||
|
/**
|
||||||
|
The YGLayout that is attached to this view. It is lazily created.
|
||||||
|
*/
|
||||||
|
@property(nonatomic, readonly, strong) YGLayout* yoga;
|
||||||
|
/**
|
||||||
|
Indicates whether or not Yoga is enabled
|
||||||
|
*/
|
||||||
|
@property(nonatomic, readonly, assign) BOOL isYogaEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
37
YogaKit/Source/UIView+Yoga.m
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
#import "UIView+Yoga.h"
|
||||||
|
#import "YGLayout+Private.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isYogaEnabled {
|
||||||
|
return objc_getAssociatedObject(self, kYGYogaAssociatedKey) != nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block {
|
||||||
|
if (block != nil) {
|
||||||
|
block(self.yoga);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
17
YogaKit/Source/YGLayout+Private.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <yoga/Yoga.h>
|
||||||
|
#import "YGLayout.h"
|
||||||
|
|
||||||
|
@interface YGLayout ()
|
||||||
|
|
||||||
|
@property(nonatomic, assign, readonly) YGNodeRef node;
|
||||||
|
|
||||||
|
- (instancetype)initWithView:(UIView*)view;
|
||||||
|
|
||||||
|
@end
|
174
YogaKit/Source/YGLayout.h
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import <yoga/YGEnums.h>
|
||||||
|
#import <yoga/YGMacros.h>
|
||||||
|
#import <yoga/Yoga.h>
|
||||||
|
|
||||||
|
YG_EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
extern YGValue YGPointValue(CGFloat value) NS_SWIFT_UNAVAILABLE(
|
||||||
|
"Use the swift Int and FloatingPoint extensions instead");
|
||||||
|
extern YGValue YGPercentValue(CGFloat value) NS_SWIFT_UNAVAILABLE(
|
||||||
|
"Use the swift Int and FloatingPoint extensions instead");
|
||||||
|
|
||||||
|
YG_EXTERN_C_END
|
||||||
|
|
||||||
|
typedef NS_OPTIONS(NSInteger, YGDimensionFlexibility) {
|
||||||
|
YGDimensionFlexibilityFlexibleWidth = 1 << 0,
|
||||||
|
YGDimensionFlexibilityFlexibleHeight = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface YGLayout : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
Make default init unavailable, as it will not initialise YGNode which is
|
||||||
|
required for the setters and getters of YGLayout's properties to work properly.
|
||||||
|
*/
|
||||||
|
- (instancetype)init
|
||||||
|
__attribute__((unavailable("you are not meant to initialise YGLayout")));
|
||||||
|
|
||||||
|
/**
|
||||||
|
Make default init unavailable, as it will not initialise YGNode which is
|
||||||
|
required for the setters and getters of YGLayout's properties to work properly.
|
||||||
|
*/
|
||||||
|
+ (instancetype)new
|
||||||
|
__attribute__((unavailable("you are not meant to initialise YGLayout")));
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 flex;
|
||||||
|
@property(nonatomic, readwrite, assign) CGFloat flexGrow;
|
||||||
|
@property(nonatomic, readwrite, assign) CGFloat flexShrink;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue flexBasis;
|
||||||
|
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue left;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue top;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue right;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue bottom;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue start;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue end;
|
||||||
|
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue marginLeft;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue marginTop;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue marginRight;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue marginBottom;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue marginStart;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue marginEnd;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue marginHorizontal;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue marginVertical;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue margin;
|
||||||
|
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue paddingLeft;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue paddingTop;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue paddingRight;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue paddingBottom;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue paddingStart;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue paddingEnd;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue paddingHorizontal;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue paddingVertical;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue 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) YGValue width;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue height;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue minWidth;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue minHeight;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue maxWidth;
|
||||||
|
@property(nonatomic, readwrite, assign) YGValue 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:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
dimensionFlexibility:(YGDimensionFlexibility)dimensionFlexibility
|
||||||
|
NS_SWIFT_NAME(applyLayout(preservingOrigin:dimensionFlexibility:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 size of the view based on provided constraints. Pass NaN for an
|
||||||
|
unconstrained dimension.
|
||||||
|
*/
|
||||||
|
- (CGSize)calculateLayoutWithSize:(CGSize)size
|
||||||
|
NS_SWIFT_NAME(calculateLayout(with:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
510
YogaKit/Source/YGLayout.m
Normal file
@@ -0,0 +1,510 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "UIView+Yoga.h"
|
||||||
|
#import "YGLayout+Private.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) \
|
||||||
|
-(YGValue)lowercased_name { \
|
||||||
|
return YGNodeStyleGet##capitalized_name(self.node); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
-(void)set##capitalized_name : (YGValue)lowercased_name { \
|
||||||
|
switch (lowercased_name.unit) { \
|
||||||
|
case YGUnitUndefined: \
|
||||||
|
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitPoint: \
|
||||||
|
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitPercent: \
|
||||||
|
YGNodeStyleSet##capitalized_name##Percent( \
|
||||||
|
self.node, lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
NSAssert(NO, @"Not implemented"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YG_AUTO_VALUE_PROPERTY(lowercased_name, capitalized_name) \
|
||||||
|
-(YGValue)lowercased_name { \
|
||||||
|
return YGNodeStyleGet##capitalized_name(self.node); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
-(void)set##capitalized_name : (YGValue)lowercased_name { \
|
||||||
|
switch (lowercased_name.unit) { \
|
||||||
|
case YGUnitPoint: \
|
||||||
|
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitPercent: \
|
||||||
|
YGNodeStyleSet##capitalized_name##Percent( \
|
||||||
|
self.node, lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitAuto: \
|
||||||
|
YGNodeStyleSet##capitalized_name##Auto(self.node); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
NSAssert(NO, @"Not implemented"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YG_EDGE_PROPERTY_GETTER( \
|
||||||
|
type, lowercased_name, capitalized_name, property, edge) \
|
||||||
|
-(type)lowercased_name { \
|
||||||
|
return YGNodeStyleGet##property(self.node, edge); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YG_EDGE_PROPERTY_SETTER( \
|
||||||
|
lowercased_name, capitalized_name, property, edge) \
|
||||||
|
-(void)set##capitalized_name : (CGFloat)lowercased_name { \
|
||||||
|
YGNodeStyleSet##property(self.node, edge, lowercased_name); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YG_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
|
||||||
|
YG_EDGE_PROPERTY_GETTER( \
|
||||||
|
CGFloat, lowercased_name, capitalized_name, property, edge) \
|
||||||
|
YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
|
||||||
|
|
||||||
|
#define YG_VALUE_EDGE_PROPERTY_SETTER( \
|
||||||
|
objc_lowercased_name, objc_capitalized_name, c_name, edge) \
|
||||||
|
-(void)set##objc_capitalized_name : (YGValue)objc_lowercased_name { \
|
||||||
|
switch (objc_lowercased_name.unit) { \
|
||||||
|
case YGUnitUndefined: \
|
||||||
|
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitPoint: \
|
||||||
|
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitPercent: \
|
||||||
|
YGNodeStyleSet##c_name##Percent( \
|
||||||
|
self.node, edge, objc_lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
NSAssert(NO, @"Not implemented"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YG_VALUE_EDGE_PROPERTY( \
|
||||||
|
lowercased_name, capitalized_name, property, edge) \
|
||||||
|
YG_EDGE_PROPERTY_GETTER( \
|
||||||
|
YGValue, lowercased_name, capitalized_name, property, edge) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY_SETTER( \
|
||||||
|
lowercased_name, capitalized_name, property, edge)
|
||||||
|
|
||||||
|
#define YG_VALUE_EDGES_PROPERTIES(lowercased_name, capitalized_name) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY( \
|
||||||
|
lowercased_name##Left, \
|
||||||
|
capitalized_name##Left, \
|
||||||
|
capitalized_name, \
|
||||||
|
YGEdgeLeft) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY( \
|
||||||
|
lowercased_name##Top, \
|
||||||
|
capitalized_name##Top, \
|
||||||
|
capitalized_name, \
|
||||||
|
YGEdgeTop) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY( \
|
||||||
|
lowercased_name##Right, \
|
||||||
|
capitalized_name##Right, \
|
||||||
|
capitalized_name, \
|
||||||
|
YGEdgeRight) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY( \
|
||||||
|
lowercased_name##Bottom, \
|
||||||
|
capitalized_name##Bottom, \
|
||||||
|
capitalized_name, \
|
||||||
|
YGEdgeBottom) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY( \
|
||||||
|
lowercased_name##Start, \
|
||||||
|
capitalized_name##Start, \
|
||||||
|
capitalized_name, \
|
||||||
|
YGEdgeStart) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY( \
|
||||||
|
lowercased_name##End, \
|
||||||
|
capitalized_name##End, \
|
||||||
|
capitalized_name, \
|
||||||
|
YGEdgeEnd) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY( \
|
||||||
|
lowercased_name##Horizontal, \
|
||||||
|
capitalized_name##Horizontal, \
|
||||||
|
capitalized_name, \
|
||||||
|
YGEdgeHorizontal) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY( \
|
||||||
|
lowercased_name##Vertical, \
|
||||||
|
capitalized_name##Vertical, \
|
||||||
|
capitalized_name, \
|
||||||
|
YGEdgeVertical) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY( \
|
||||||
|
lowercased_name, capitalized_name, capitalized_name, YGEdgeAll)
|
||||||
|
|
||||||
|
YGValue YGPointValue(CGFloat value) {
|
||||||
|
return (YGValue){.value = value, .unit = YGUnitPoint};
|
||||||
|
}
|
||||||
|
|
||||||
|
YGValue YGPercentValue(CGFloat value) {
|
||||||
|
return (YGValue){.value = value, .unit = YGUnitPercent};
|
||||||
|
}
|
||||||
|
|
||||||
|
static YGConfigRef globalConfig;
|
||||||
|
|
||||||
|
@interface YGLayout ()
|
||||||
|
|
||||||
|
@property(nonatomic, weak, readonly) UIView* view;
|
||||||
|
@property(nonatomic, assign, readonly) BOOL isUIView;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation YGLayout
|
||||||
|
|
||||||
|
@synthesize isEnabled = _isEnabled;
|
||||||
|
@synthesize isIncludedInLayout = _isIncludedInLayout;
|
||||||
|
@synthesize node = _node;
|
||||||
|
|
||||||
|
+ (void)initialize {
|
||||||
|
globalConfig = YGConfigNew();
|
||||||
|
YGConfigSetExperimentalFeatureEnabled(
|
||||||
|
globalConfig, YGExperimentalFeatureWebFlexBasis, true);
|
||||||
|
YGConfigSetPointScaleFactor(globalConfig, [UIScreen mainScreen].scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithView:(UIView*)view {
|
||||||
|
if (self = [super init]) {
|
||||||
|
_view = view;
|
||||||
|
_node = YGNodeNewWithConfig(globalConfig);
|
||||||
|
YGNodeSetContext(_node, (__bridge void*)view);
|
||||||
|
_isEnabled = NO;
|
||||||
|
_isIncludedInLayout = YES;
|
||||||
|
_isUIView = [view isMemberOfClass:[UIView class]];
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (!YGNodeHasMeasureFunc(node)) {
|
||||||
|
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, flex, Flex)
|
||||||
|
YG_PROPERTY(CGFloat, flexGrow, FlexGrow)
|
||||||
|
YG_PROPERTY(CGFloat, flexShrink, FlexShrink)
|
||||||
|
YG_AUTO_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_AUTO_VALUE_PROPERTY(width, Width)
|
||||||
|
YG_AUTO_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)
|
||||||
|
|
||||||
|
YG_EDGE_PROPERTY(columnGap, ColumnGap, Gap, YGGutterColumn)
|
||||||
|
YG_EDGE_PROPERTY(rowGap, RowGap, Gap, YGGutterRow)
|
||||||
|
YG_EDGE_PROPERTY(gap, Gap, Gap, YGGutterAll)
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
|
||||||
|
dimensionFlexibility:
|
||||||
|
(YGDimensionFlexibility)dimensionFlexibility {
|
||||||
|
CGSize size = self.view.bounds.size;
|
||||||
|
if (dimensionFlexibility & YGDimensionFlexibilityFlexibleWidth) {
|
||||||
|
size.width = YGUndefined;
|
||||||
|
}
|
||||||
|
if (dimensionFlexibility & YGDimensionFlexibilityFlexibleHeight) {
|
||||||
|
size.height = YGUndefined;
|
||||||
|
}
|
||||||
|
[self calculateLayoutWithSize:size];
|
||||||
|
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)intrinsicSize {
|
||||||
|
const CGSize constrainedSize = {
|
||||||
|
.width = YGUndefined,
|
||||||
|
.height = YGUndefined,
|
||||||
|
};
|
||||||
|
return [self calculateLayoutWithSize:constrainedSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (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),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Private
|
||||||
|
|
||||||
|
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);
|
||||||
|
CGSize sizeThatFits = CGSizeZero;
|
||||||
|
|
||||||
|
// The default implementation of sizeThatFits: returns the existing size of
|
||||||
|
// the view. That means that if we want to layout an empty UIView, which
|
||||||
|
// already has got a frame set, its measured size should be CGSizeZero, but
|
||||||
|
// UIKit returns the existing size.
|
||||||
|
//
|
||||||
|
// See https://github.com/facebook/yoga/issues/606 for more information.
|
||||||
|
if (!view.yoga.isUIView || [view.subviews count] > 0) {
|
||||||
|
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.isEnabled && 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
YGNodeRemoveAllChildren(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
45
YogaKit/Source/YGLayoutExtensions.swift
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import yoga;
|
||||||
|
postfix operator %
|
||||||
|
|
||||||
|
extension Int {
|
||||||
|
public static postfix func %(value: Int) -> YGValue {
|
||||||
|
return YGValue(value: Float(value), unit: .percent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Float {
|
||||||
|
public static postfix func %(value: Float) -> YGValue {
|
||||||
|
return YGValue(value: value, unit: .percent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CGFloat {
|
||||||
|
public static postfix func %(value: CGFloat) -> YGValue {
|
||||||
|
return YGValue(value: Float(value), unit: .percent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension YGValue : ExpressibleByIntegerLiteral, ExpressibleByFloatLiteral {
|
||||||
|
public init(integerLiteral value: Int) {
|
||||||
|
self = YGValue(value: Float(value), unit: .point)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(floatLiteral value: Float) {
|
||||||
|
self = YGValue(value: value, unit: .point)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(_ value: Float) {
|
||||||
|
self = YGValue(value: value, unit: .point)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(_ value: CGFloat) {
|
||||||
|
self = YGValue(value: Float(value), unit: .point)
|
||||||
|
}
|
||||||
|
}
|
22
YogaKit/Tests/Info.plist
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?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>com.facebook.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>BNDL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
749
YogaKit/Tests/YogaKitTests.m
Normal file
@@ -0,0 +1,749 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <XCTest/XCTest.h>
|
||||||
|
|
||||||
|
#import <YogaKit/UIView+Yoga.h>
|
||||||
|
#import <YogaKit/YGLayout+Private.h>
|
||||||
|
#import <yoga/Yoga.h>
|
||||||
|
|
||||||
|
@interface YogaKitTests : XCTestCase
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation YogaKitTests
|
||||||
|
|
||||||
|
- (void)testConfigureLayoutIsNoOpWithNilBlock {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
id block = nil;
|
||||||
|
XCTAssertNoThrow([view configureLayoutWithBlock:block]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testConfigureLayoutBlockWorksWithValidBlock {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
[view configureLayoutWithBlock:^(YGLayout* layout) {
|
||||||
|
XCTAssertNotNil(layout);
|
||||||
|
layout.isEnabled = YES;
|
||||||
|
layout.width = YGPointValue(25);
|
||||||
|
}];
|
||||||
|
|
||||||
|
XCTAssertTrue(view.yoga.isEnabled);
|
||||||
|
XCTAssertEqual(view.yoga.width.value, 25);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testNodesAreDeallocedWithSingleView {
|
||||||
|
__weak YGLayout* layoutRef = nil;
|
||||||
|
|
||||||
|
@autoreleasepool {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
view.yoga.flexBasis = YGPointValue(1);
|
||||||
|
|
||||||
|
layoutRef = view.yoga;
|
||||||
|
XCTAssertNotNil(layoutRef);
|
||||||
|
|
||||||
|
view = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertNil(layoutRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testNodesAreDeallocedCascade {
|
||||||
|
__weak YGLayout* topLayout = nil;
|
||||||
|
__weak YGLayout* subviewLayout = nil;
|
||||||
|
|
||||||
|
@autoreleasepool {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
topLayout = view.yoga;
|
||||||
|
topLayout.flexBasis = YGPointValue(1);
|
||||||
|
|
||||||
|
UIView* subview = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subviewLayout = subview.yoga;
|
||||||
|
subviewLayout.flexBasis = YGPointValue(1);
|
||||||
|
|
||||||
|
view = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertNil(topLayout);
|
||||||
|
XCTAssertNil(subviewLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testIsEnabled {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
XCTAssertFalse(view.yoga.isEnabled);
|
||||||
|
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
XCTAssertTrue(view.yoga.isEnabled);
|
||||||
|
|
||||||
|
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.yoga.intrinsicSize);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testSizeThatFitsSmoke {
|
||||||
|
UIView* container = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
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.yoga.isEnabled = YES;
|
||||||
|
longTextLabel.yoga.flexShrink = 1;
|
||||||
|
[container addSubview:longTextLabel];
|
||||||
|
|
||||||
|
UIView* textBadgeView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
textBadgeView.yoga.isEnabled = YES;
|
||||||
|
textBadgeView.yoga.margin = YGPointValue(0);
|
||||||
|
textBadgeView.yoga.width = YGPointValue(10);
|
||||||
|
textBadgeView.yoga.height = YGPointValue(10);
|
||||||
|
[container addSubview:textBadgeView];
|
||||||
|
|
||||||
|
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)testSizeThatFitsEmptyView {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 200, 200)];
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
const CGSize viewSize = view.yoga.intrinsicSize;
|
||||||
|
XCTAssertEqual(viewSize.height, 0);
|
||||||
|
XCTAssertEqual(viewSize.width, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (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 = YGPointValue(0);
|
||||||
|
view.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:view];
|
||||||
|
|
||||||
|
UIView* view2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
view2.yoga.isEnabled = YES;
|
||||||
|
view2.yoga.marginTop = YGPointValue(25);
|
||||||
|
view2.yoga.flexBasis = YGPointValue(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)testContainerWithFlexibleWidthGetsCorrectlySized {
|
||||||
|
UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
view.yoga.width = YGPointValue(100);
|
||||||
|
view.yoga.height = YGPointValue(100);
|
||||||
|
[container addSubview:view];
|
||||||
|
|
||||||
|
[container.yoga
|
||||||
|
applyLayoutPreservingOrigin:YES
|
||||||
|
dimensionFlexibility:YGDimensionFlexibilityFlexibleWidth];
|
||||||
|
XCTAssertEqual(100, container.frame.size.width);
|
||||||
|
XCTAssertEqual(200, container.frame.size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testContainerWithFlexibleHeightGetsCorrectlySized {
|
||||||
|
UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
view.yoga.width = YGPointValue(100);
|
||||||
|
view.yoga.height = YGPointValue(100);
|
||||||
|
[container addSubview:view];
|
||||||
|
|
||||||
|
[container.yoga
|
||||||
|
applyLayoutPreservingOrigin:YES
|
||||||
|
dimensionFlexibility:YGDimensionFlexibilityFlexibleHeight];
|
||||||
|
XCTAssertEqual(200, container.frame.size.width);
|
||||||
|
XCTAssertEqual(100, container.frame.size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testContainerWithFlexibleWidthAndHeightGetsCorrectlySized {
|
||||||
|
UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
view.yoga.width = YGPointValue(100);
|
||||||
|
view.yoga.height = YGPointValue(100);
|
||||||
|
[container addSubview:view];
|
||||||
|
|
||||||
|
[container.yoga
|
||||||
|
applyLayoutPreservingOrigin:YES
|
||||||
|
dimensionFlexibility:YGDimensionFlexibilityFlexibleWidth |
|
||||||
|
YGDimensionFlexibilityFlexibleHeight];
|
||||||
|
XCTAssertEqual(100, container.frame.size.width);
|
||||||
|
XCTAssertEqual(100, container.frame.size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (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 {
|
||||||
|
const CGSize containerSize = CGSizeMake(320, 50);
|
||||||
|
|
||||||
|
UIView* container = [[UIView alloc]
|
||||||
|
initWithFrame:CGRectMake(
|
||||||
|
0, 0, containerSize.width, containerSize.height)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
|
||||||
|
UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview1.yoga.isEnabled = YES;
|
||||||
|
subview1.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview1];
|
||||||
|
|
||||||
|
UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview2.yoga.isEnabled = YES;
|
||||||
|
subview2.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview2];
|
||||||
|
|
||||||
|
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) {
|
||||||
|
totalWidth += view.bounds.size.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(
|
||||||
|
containerSize.width,
|
||||||
|
totalWidth,
|
||||||
|
@"The container's width is %.6f, the subviews take up %.6f",
|
||||||
|
containerSize.width,
|
||||||
|
totalWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testThatLayoutIsCorrectWhenWeSwapViewOrder {
|
||||||
|
const CGSize containerSize = CGSizeMake(300, 50);
|
||||||
|
|
||||||
|
UIView* container = [[UIView alloc]
|
||||||
|
initWithFrame:CGRectMake(
|
||||||
|
0, 0, containerSize.width, containerSize.height)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
|
||||||
|
UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview1.yoga.isEnabled = YES;
|
||||||
|
subview1.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview1];
|
||||||
|
|
||||||
|
UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview2.yoga.isEnabled = YES;
|
||||||
|
subview2.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview2];
|
||||||
|
|
||||||
|
UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview3.yoga.isEnabled = YES;
|
||||||
|
subview3.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview3];
|
||||||
|
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
|
||||||
|
XCTAssertTrue(CGRectEqualToRect(subview1.frame, CGRectMake(0, 0, 100, 50)));
|
||||||
|
XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50)));
|
||||||
|
XCTAssertTrue(CGRectEqualToRect(subview3.frame, CGRectMake(200, 0, 100, 50)));
|
||||||
|
|
||||||
|
[container exchangeSubviewAtIndex:2 withSubviewAtIndex:0];
|
||||||
|
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)));
|
||||||
|
|
||||||
|
// this frame shouldn't have been modified since last time.
|
||||||
|
XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50)));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testThatWeRespectIncludeInLayoutFlag {
|
||||||
|
const CGSize containerSize = CGSizeMake(300, 50);
|
||||||
|
|
||||||
|
UIView* container = [[UIView alloc]
|
||||||
|
initWithFrame:CGRectMake(
|
||||||
|
0, 0, containerSize.width, containerSize.height)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
|
||||||
|
UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview1.yoga.isEnabled = YES;
|
||||||
|
subview1.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview1];
|
||||||
|
|
||||||
|
UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview2.yoga.isEnabled = YES;
|
||||||
|
subview2.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview2];
|
||||||
|
|
||||||
|
UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview3.yoga.isEnabled = YES;
|
||||||
|
subview3.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview3];
|
||||||
|
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
|
||||||
|
for (UIView* subview in container.subviews) {
|
||||||
|
XCTAssertEqual(subview.bounds.size.width, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
subview3.yoga.isIncludedInLayout = NO;
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
|
||||||
|
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.
|
||||||
|
XCTAssertEqual(subview3.bounds.size.width, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews {
|
||||||
|
UIView* container = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
|
||||||
|
UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview1.yoga.isEnabled = YES;
|
||||||
|
subview1.yoga.isIncludedInLayout = NO;
|
||||||
|
[container addSubview:subview1];
|
||||||
|
|
||||||
|
UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview2.yoga.isEnabled = YES;
|
||||||
|
subview2.yoga.isIncludedInLayout = NO;
|
||||||
|
[container addSubview:subview2];
|
||||||
|
|
||||||
|
UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview3.yoga.isEnabled = YES;
|
||||||
|
subview3.yoga.isIncludedInLayout = YES;
|
||||||
|
[container addSubview:subview3];
|
||||||
|
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
XCTAssertEqual(container.yoga.numberOfChildren, 1);
|
||||||
|
|
||||||
|
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.yoga.isEnabled = YES;
|
||||||
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
|
||||||
|
UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview1.yoga.isEnabled = YES;
|
||||||
|
subview1.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview1];
|
||||||
|
|
||||||
|
UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview2.yoga.isEnabled = YES;
|
||||||
|
subview2.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview2];
|
||||||
|
|
||||||
|
UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview3.yoga.isEnabled = YES;
|
||||||
|
subview3.yoga.flexGrow = 1;
|
||||||
|
subview3.yoga.isIncludedInLayout = NO;
|
||||||
|
[container addSubview:subview3];
|
||||||
|
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
|
||||||
|
XCTAssertEqual(subview1.bounds.size.width, 150);
|
||||||
|
XCTAssertEqual(subview2.bounds.size.width, 150);
|
||||||
|
XCTAssertEqual(subview3.bounds.size.width, 0);
|
||||||
|
|
||||||
|
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 = YGPointValue(50);
|
||||||
|
XCTAssertTrue(view.yoga.isLeaf);
|
||||||
|
|
||||||
|
UIView* const subview = view.subviews[0];
|
||||||
|
subview.yoga.isEnabled = YES;
|
||||||
|
subview.yoga.width = YGPointValue(50);
|
||||||
|
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 = YGPointValue(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 = YGPointValue(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)testPointPercent {
|
||||||
|
XCTAssertEqual(YGPointValue(1).value, 1);
|
||||||
|
XCTAssertEqual(YGPointValue(1).unit, YGUnitPoint);
|
||||||
|
XCTAssertEqual(YGPercentValue(2).value, 2);
|
||||||
|
XCTAssertEqual(YGPercentValue(2).unit, YGUnitPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testPositionalPropertiesWork {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
|
||||||
|
view.yoga.left = YGPointValue(1);
|
||||||
|
XCTAssertEqual(view.yoga.left.value, 1);
|
||||||
|
XCTAssertEqual(view.yoga.left.unit, YGUnitPoint);
|
||||||
|
view.yoga.left = YGPercentValue(2);
|
||||||
|
XCTAssertEqual(view.yoga.left.value, 2);
|
||||||
|
XCTAssertEqual(view.yoga.left.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.right = YGPointValue(3);
|
||||||
|
XCTAssertEqual(view.yoga.right.value, 3);
|
||||||
|
XCTAssertEqual(view.yoga.right.unit, YGUnitPoint);
|
||||||
|
view.yoga.right = YGPercentValue(4);
|
||||||
|
XCTAssertEqual(view.yoga.right.value, 4);
|
||||||
|
XCTAssertEqual(view.yoga.right.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.top = YGPointValue(5);
|
||||||
|
XCTAssertEqual(view.yoga.top.value, 5);
|
||||||
|
XCTAssertEqual(view.yoga.top.unit, YGUnitPoint);
|
||||||
|
view.yoga.top = YGPercentValue(6);
|
||||||
|
XCTAssertEqual(view.yoga.top.value, 6);
|
||||||
|
XCTAssertEqual(view.yoga.top.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.bottom = YGPointValue(7);
|
||||||
|
XCTAssertEqual(view.yoga.bottom.value, 7);
|
||||||
|
XCTAssertEqual(view.yoga.bottom.unit, YGUnitPoint);
|
||||||
|
view.yoga.bottom = YGPercentValue(8);
|
||||||
|
XCTAssertEqual(view.yoga.bottom.value, 8);
|
||||||
|
XCTAssertEqual(view.yoga.bottom.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.start = YGPointValue(9);
|
||||||
|
XCTAssertEqual(view.yoga.start.value, 9);
|
||||||
|
XCTAssertEqual(view.yoga.start.unit, YGUnitPoint);
|
||||||
|
view.yoga.start = YGPercentValue(10);
|
||||||
|
XCTAssertEqual(view.yoga.start.value, 10);
|
||||||
|
XCTAssertEqual(view.yoga.start.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.end = YGPointValue(11);
|
||||||
|
XCTAssertEqual(view.yoga.end.value, 11);
|
||||||
|
XCTAssertEqual(view.yoga.end.unit, YGUnitPoint);
|
||||||
|
view.yoga.end = YGPercentValue(12);
|
||||||
|
XCTAssertEqual(view.yoga.end.value, 12);
|
||||||
|
XCTAssertEqual(view.yoga.end.unit, YGUnitPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testMarginPropertiesWork {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
|
||||||
|
view.yoga.margin = YGPointValue(1);
|
||||||
|
XCTAssertEqual(view.yoga.margin.value, 1);
|
||||||
|
XCTAssertEqual(view.yoga.margin.unit, YGUnitPoint);
|
||||||
|
view.yoga.margin = YGPercentValue(2);
|
||||||
|
XCTAssertEqual(view.yoga.margin.value, 2);
|
||||||
|
XCTAssertEqual(view.yoga.margin.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginHorizontal = YGPointValue(3);
|
||||||
|
XCTAssertEqual(view.yoga.marginHorizontal.value, 3);
|
||||||
|
XCTAssertEqual(view.yoga.marginHorizontal.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginHorizontal = YGPercentValue(4);
|
||||||
|
XCTAssertEqual(view.yoga.marginHorizontal.value, 4);
|
||||||
|
XCTAssertEqual(view.yoga.marginHorizontal.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginVertical = YGPointValue(5);
|
||||||
|
XCTAssertEqual(view.yoga.marginVertical.value, 5);
|
||||||
|
XCTAssertEqual(view.yoga.marginVertical.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginVertical = YGPercentValue(6);
|
||||||
|
XCTAssertEqual(view.yoga.marginVertical.value, 6);
|
||||||
|
XCTAssertEqual(view.yoga.marginVertical.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginLeft = YGPointValue(7);
|
||||||
|
XCTAssertEqual(view.yoga.marginLeft.value, 7);
|
||||||
|
XCTAssertEqual(view.yoga.marginLeft.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginLeft = YGPercentValue(8);
|
||||||
|
XCTAssertEqual(view.yoga.marginLeft.value, 8);
|
||||||
|
XCTAssertEqual(view.yoga.marginLeft.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginRight = YGPointValue(9);
|
||||||
|
XCTAssertEqual(view.yoga.marginRight.value, 9);
|
||||||
|
XCTAssertEqual(view.yoga.marginRight.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginRight = YGPercentValue(10);
|
||||||
|
XCTAssertEqual(view.yoga.marginRight.value, 10);
|
||||||
|
XCTAssertEqual(view.yoga.marginRight.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginTop = YGPointValue(11);
|
||||||
|
XCTAssertEqual(view.yoga.marginTop.value, 11);
|
||||||
|
XCTAssertEqual(view.yoga.marginTop.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginTop = YGPercentValue(12);
|
||||||
|
XCTAssertEqual(view.yoga.marginTop.value, 12);
|
||||||
|
XCTAssertEqual(view.yoga.marginTop.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginBottom = YGPointValue(13);
|
||||||
|
XCTAssertEqual(view.yoga.marginBottom.value, 13);
|
||||||
|
XCTAssertEqual(view.yoga.marginBottom.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginBottom = YGPercentValue(14);
|
||||||
|
XCTAssertEqual(view.yoga.marginBottom.value, 14);
|
||||||
|
XCTAssertEqual(view.yoga.marginBottom.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginStart = YGPointValue(15);
|
||||||
|
XCTAssertEqual(view.yoga.marginStart.value, 15);
|
||||||
|
XCTAssertEqual(view.yoga.marginStart.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginStart = YGPercentValue(16);
|
||||||
|
XCTAssertEqual(view.yoga.marginStart.value, 16);
|
||||||
|
XCTAssertEqual(view.yoga.marginStart.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginEnd = YGPointValue(17);
|
||||||
|
XCTAssertEqual(view.yoga.marginEnd.value, 17);
|
||||||
|
XCTAssertEqual(view.yoga.marginEnd.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginEnd = YGPercentValue(18);
|
||||||
|
XCTAssertEqual(view.yoga.marginEnd.value, 18);
|
||||||
|
XCTAssertEqual(view.yoga.marginEnd.unit, YGUnitPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testPaddingPropertiesWork {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
|
||||||
|
view.yoga.padding = YGPointValue(1);
|
||||||
|
XCTAssertEqual(view.yoga.padding.value, 1);
|
||||||
|
XCTAssertEqual(view.yoga.padding.unit, YGUnitPoint);
|
||||||
|
view.yoga.padding = YGPercentValue(2);
|
||||||
|
XCTAssertEqual(view.yoga.padding.value, 2);
|
||||||
|
XCTAssertEqual(view.yoga.padding.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingHorizontal = YGPointValue(3);
|
||||||
|
XCTAssertEqual(view.yoga.paddingHorizontal.value, 3);
|
||||||
|
XCTAssertEqual(view.yoga.paddingHorizontal.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingHorizontal = YGPercentValue(4);
|
||||||
|
XCTAssertEqual(view.yoga.paddingHorizontal.value, 4);
|
||||||
|
XCTAssertEqual(view.yoga.paddingHorizontal.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingVertical = YGPointValue(5);
|
||||||
|
XCTAssertEqual(view.yoga.paddingVertical.value, 5);
|
||||||
|
XCTAssertEqual(view.yoga.paddingVertical.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingVertical = YGPercentValue(6);
|
||||||
|
XCTAssertEqual(view.yoga.paddingVertical.value, 6);
|
||||||
|
XCTAssertEqual(view.yoga.paddingVertical.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingLeft = YGPointValue(7);
|
||||||
|
XCTAssertEqual(view.yoga.paddingLeft.value, 7);
|
||||||
|
XCTAssertEqual(view.yoga.paddingLeft.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingLeft = YGPercentValue(8);
|
||||||
|
XCTAssertEqual(view.yoga.paddingLeft.value, 8);
|
||||||
|
XCTAssertEqual(view.yoga.paddingLeft.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingRight = YGPointValue(9);
|
||||||
|
XCTAssertEqual(view.yoga.paddingRight.value, 9);
|
||||||
|
XCTAssertEqual(view.yoga.paddingRight.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingRight = YGPercentValue(10);
|
||||||
|
XCTAssertEqual(view.yoga.paddingRight.value, 10);
|
||||||
|
XCTAssertEqual(view.yoga.paddingRight.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingTop = YGPointValue(11);
|
||||||
|
XCTAssertEqual(view.yoga.paddingTop.value, 11);
|
||||||
|
XCTAssertEqual(view.yoga.paddingTop.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingTop = YGPercentValue(12);
|
||||||
|
XCTAssertEqual(view.yoga.paddingTop.value, 12);
|
||||||
|
XCTAssertEqual(view.yoga.paddingTop.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingBottom = YGPointValue(13);
|
||||||
|
XCTAssertEqual(view.yoga.paddingBottom.value, 13);
|
||||||
|
XCTAssertEqual(view.yoga.paddingBottom.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingBottom = YGPercentValue(14);
|
||||||
|
XCTAssertEqual(view.yoga.paddingBottom.value, 14);
|
||||||
|
XCTAssertEqual(view.yoga.paddingBottom.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingStart = YGPointValue(15);
|
||||||
|
XCTAssertEqual(view.yoga.paddingStart.value, 15);
|
||||||
|
XCTAssertEqual(view.yoga.paddingStart.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingStart = YGPercentValue(16);
|
||||||
|
XCTAssertEqual(view.yoga.paddingStart.value, 16);
|
||||||
|
XCTAssertEqual(view.yoga.paddingStart.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingEnd = YGPointValue(17);
|
||||||
|
XCTAssertEqual(view.yoga.paddingEnd.value, 17);
|
||||||
|
XCTAssertEqual(view.yoga.paddingEnd.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingEnd = YGPercentValue(18);
|
||||||
|
XCTAssertEqual(view.yoga.paddingEnd.value, 18);
|
||||||
|
XCTAssertEqual(view.yoga.paddingEnd.unit, YGUnitPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testBorderWidthPropertiesWork {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
|
||||||
|
view.yoga.borderWidth = 1;
|
||||||
|
XCTAssertEqual(view.yoga.borderWidth, 1);
|
||||||
|
|
||||||
|
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
|
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.7.0)
|
||||||
|
- YogaKit (1.7.0):
|
||||||
|
- Yoga (~> 1.7)
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- IGListKit (~> 2.1.0)
|
||||||
|
- YogaKit (from `../../YogaKit.podspec`)
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
YogaKit:
|
||||||
|
:path: ../../YogaKit.podspec
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
IGListKit: b826c68ef7a4ae1626c09d4d3e1ea7a169e6c36e
|
||||||
|
Yoga: 2ed1d7accfef3610a67f58c0cf101a0662137f2c
|
||||||
|
YogaKit: 31576530e8fcae3175469719ec3212397403330b
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: 216f8e7127767709e0e43f3711208d238fa5c404
|
||||||
|
|
||||||
|
COCOAPODS: 1.1.1
|
529
YogaKit/YogaKitSample/YogaKitSample.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,529 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// !$*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>
|
@@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "0820"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "13687D421DF8748300E7C260"
|
||||||
|
BuildableName = "YogaKitSample.app"
|
||||||
|
BlueprintName = "YogaKitSample"
|
||||||
|
ReferencedContainer = "container:YogaKitSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "638A944E1E215CC800A726AD"
|
||||||
|
BuildableName = "YogaKitSampleTests.xctest"
|
||||||
|
BlueprintName = "YogaKitSampleTests"
|
||||||
|
ReferencedContainer = "container:YogaKitSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "13687D421DF8748300E7C260"
|
||||||
|
BuildableName = "YogaKitSample.app"
|
||||||
|
BlueprintName = "YogaKitSample"
|
||||||
|
ReferencedContainer = "container:YogaKitSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "13687D421DF8748300E7C260"
|
||||||
|
BuildableName = "YogaKitSample.app"
|
||||||
|
BlueprintName = "YogaKitSample"
|
||||||
|
ReferencedContainer = "container:YogaKitSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "13687D421DF8748300E7C260"
|
||||||
|
BuildableName = "YogaKitSample.app"
|
||||||
|
BlueprintName = "YogaKitSample"
|
||||||
|
ReferencedContainer = "container:YogaKitSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
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>
|
26
YogaKit/YogaKitSample/YogaKitSample/AppDelegate.swift
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE 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"
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE 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,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import IGListKit
|
||||||
|
import YogaKit
|
||||||
|
|
||||||
|
struct DemoItem {
|
||||||
|
let name: String
|
||||||
|
root.backgroundColor = .red
|
||||||
|
root.yoga.isEnabled = true
|
||||||
|
root.yoga.width = YGValue(self.view.bounds.size.width)
|
||||||
|
root.yoga.height = YGValue(self.view.bounds.size.height)
|
||||||
|
root.yoga.alignItems = .center
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
51
YogaKit/YogaKitSample/YogaKitSample/ViewController.m
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE 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 = YGPointValue(self.view.bounds.size.width);
|
||||||
|
root.yoga.height = YGPointValue(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 = YGPointValue(100);
|
||||||
|
child1.yoga.height = YGPointValue(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,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE 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.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.width = YGValue(containerSize.width)
|
||||||
|
layout.height = YGValue(containerSize.height)
|
||||||
|
layout.alignItems = .center
|
||||||
|
layout.justifyContent = .center
|
||||||
|
}
|
||||||
|
|
||||||
|
let child1 = UIView()
|
||||||
|
child1.backgroundColor = .blue
|
||||||
|
child1.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.width = 100
|
||||||
|
layout.height = 10
|
||||||
|
layout.marginBottom = 25
|
||||||
|
}
|
||||||
|
root.addSubview(child1)
|
||||||
|
|
||||||
|
let child2 = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
|
||||||
|
child2.backgroundColor = .green
|
||||||
|
child2.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.alignSelf = .flexEnd
|
||||||
|
}
|
||||||
|
root.addSubview(child2)
|
||||||
|
|
||||||
|
let child3 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
|
||||||
|
child3.backgroundColor = .yellow
|
||||||
|
child3.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.alignSelf = .flexStart
|
||||||
|
}
|
||||||
|
root.addSubview(child3)
|
||||||
|
|
||||||
|
root.yoga.applyLayout(preservingOrigin: true)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE 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.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.flexDirection = .column
|
||||||
|
layout.justifyContent = .spaceAround
|
||||||
|
}
|
||||||
|
|
||||||
|
contentView.backgroundColor = .clear
|
||||||
|
contentView.layer.borderColor = UIColor.lightGray.cgColor
|
||||||
|
contentView.layer.borderWidth = 1.0
|
||||||
|
contentView.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.height = 300
|
||||||
|
layout.width = YGValue(self.view.bounds.size.width)
|
||||||
|
layout.flexDirection = .row
|
||||||
|
layout.justifyContent = .center
|
||||||
|
layout.paddingHorizontal = 25
|
||||||
|
}
|
||||||
|
self.view.addSubview(contentView)
|
||||||
|
|
||||||
|
let redView = UIView(frame: .zero)
|
||||||
|
redView.backgroundColor = .red
|
||||||
|
redView.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.flexGrow = 1
|
||||||
|
layout.flexShrink = 1
|
||||||
|
}
|
||||||
|
contentView.addSubview(redView)
|
||||||
|
|
||||||
|
disappearingView.backgroundColor = .blue
|
||||||
|
disappearingView.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.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.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.height = 300
|
||||||
|
layout.width = 300
|
||||||
|
layout.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,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE 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.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.flexDirection = .column
|
||||||
|
layout.justifyContent = .flexEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
label.textAlignment = .center
|
||||||
|
label.numberOfLines = 1
|
||||||
|
label.yoga.isIncludedInLayout = false
|
||||||
|
contentView.addSubview(label)
|
||||||
|
|
||||||
|
let border = UIView(frame: .zero)
|
||||||
|
border.backgroundColor = .lightGray
|
||||||
|
border.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.height = 0.5
|
||||||
|
layout.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
|
||||||
|
}
|
||||||
|
}
|
21
android/README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# YogaLayout [](https://facebook.github.io/yoga/docs/api/android/) [](https://facebook.github.io/yoga/docs/api/android/) [](https://bintray.com/facebook/maven/com.facebook.yoga.android%3Ayoga-layout/_latestVersion)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
YogaLayout is available via jcenter:
|
||||||
|
|
||||||
|
implementation 'com.facebook.yoga.android:yoga-layout:1.16.0'
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Check out the docs [here](https://yogalayout.com/getting-started/standalone/).
|
||||||
|
|
||||||
|
We also have a sample project. To try it, clone the repo and run (with a device attached)
|
||||||
|
|
||||||
|
buck install -r android/sample
|
||||||
|
|
||||||
|
## 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 file for how to help out.
|
38
android/build.gradle
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace 'com.facebook.yoga.android'
|
||||||
|
|
||||||
|
compileSdkVersion rootProject.compileSdkVersion
|
||||||
|
buildToolsVersion rootProject.buildToolsVersion
|
||||||
|
ndkVersion rootProject.ndkVersion
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion rootProject.minSdkVersion
|
||||||
|
targetSdkVersion rootProject.targetSdkVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
targetCompatibility rootProject.targetCompatibilityVersion
|
||||||
|
sourceCompatibility rootProject.sourceCompatibilityVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api project(':yoga')
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't build Javadoc at this time as we can't disable "BUCK" files
|
||||||
|
// from mistakenly getting parsed as Java.
|
||||||
|
tasks.withType(Javadoc).all {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.vanniktech.maven.publish'
|
12
android/gradle.properties
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
# file in the root directory of this source tree.
|
||||||
|
#
|
||||||
|
|
||||||
|
GROUP=com.facebook.yoga.android
|
||||||
|
POM_NAME=YogaLayout
|
||||||
|
POM_DESCRIPTION=YogaLayout
|
||||||
|
POM_ARTIFACT_ID=yoga-layout
|
||||||
|
POM_PACKAGING=aar
|
48
android/sample/AndroidManifest.xml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?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"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0"
|
||||||
|
>
|
||||||
|
|
||||||
|
<variable name="applicationId" value="com.facebook.yoga"/>
|
||||||
|
<variable name="app_label" value="Yoga Sample App"/>
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:allowBackup="false"
|
||||||
|
android:theme="@style/NoTitleBarWhiteBG"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".BenchmarkActivity"
|
||||||
|
android:exported="false"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
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
|
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v4.app.FragmentPagerAdapter;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentTransaction;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
import com.facebook.yoga.android.YogaViewLayoutFactory;
|
||||||
|
|
||||||
|
public class BenchmarkActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
LayoutInflater.from(this).setFactory(YogaViewLayoutFactory.getInstance());
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setContentView(R.layout.benchmark_select_layout);
|
||||||
|
|
||||||
|
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
|
||||||
|
viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager()));
|
||||||
|
|
||||||
|
final ActionBar actionBar = getSupportActionBar();
|
||||||
|
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||||
|
|
||||||
|
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
|
||||||
|
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
|
||||||
|
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
|
||||||
|
viewPager.setCurrentItem(tab.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
actionBar.addTab(
|
||||||
|
actionBar.newTab()
|
||||||
|
.setText("Inflate")
|
||||||
|
.setTabListener(tabListener));
|
||||||
|
actionBar.addTab(
|
||||||
|
actionBar.newTab()
|
||||||
|
.setText("Measure")
|
||||||
|
.setTabListener(tabListener));
|
||||||
|
actionBar.addTab(
|
||||||
|
actionBar.newTab()
|
||||||
|
.setText("Layout")
|
||||||
|
.setTabListener(tabListener));
|
||||||
|
|
||||||
|
viewPager.setOnPageChangeListener(
|
||||||
|
new ViewPager.SimpleOnPageChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onPageSelected(int position) {
|
||||||
|
// When swiping between pages, select the
|
||||||
|
// corresponding tab.
|
||||||
|
actionBar.setSelectedNavigationItem(position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
viewPager.setOffscreenPageLimit(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.action_bar_benchmark, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
// There is only one option
|
||||||
|
Intent intent = new Intent(this, MainActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
this.finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PagerAdapter extends FragmentPagerAdapter {
|
||||||
|
public PagerAdapter(FragmentManager fm) {
|
||||||
|
super(fm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment getItem(int i) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
return new BenchmarkInflate();
|
||||||
|
case 1:
|
||||||
|
return new BenchmarkMeasure();
|
||||||
|
default:
|
||||||
|
return new BenchmarkLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.lang.Math;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.os.Environment;
|
||||||
|
|
||||||
|
import static java.util.Collections.sort;
|
||||||
|
|
||||||
|
public class BenchmarkAggregator {
|
||||||
|
|
||||||
|
private final int GRAPH_WIDTH = 30;
|
||||||
|
private final int GRAPH_HEIGHT = 6;
|
||||||
|
|
||||||
|
private List<Long> times;
|
||||||
|
private boolean tracing;
|
||||||
|
private long lastTraceStart;
|
||||||
|
|
||||||
|
private boolean statsFresh;
|
||||||
|
private long mean;
|
||||||
|
private long variance;
|
||||||
|
private long stddev;
|
||||||
|
private long min;
|
||||||
|
private long max;
|
||||||
|
private long p10;
|
||||||
|
private long p50;
|
||||||
|
private long p90;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public BenchmarkAggregator(String name) {
|
||||||
|
times = new ArrayList<>();
|
||||||
|
tracing = false;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startTrace() {
|
||||||
|
if (tracing) {
|
||||||
|
throw new RuntimeException("Cannot start trace while running previous one");
|
||||||
|
}
|
||||||
|
tracing = true;
|
||||||
|
lastTraceStart = System.nanoTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endTrace() {
|
||||||
|
if (!tracing) {
|
||||||
|
throw new RuntimeException("Cannot stop trace if none are running!");
|
||||||
|
}
|
||||||
|
times.add(System.nanoTime() - lastTraceStart);
|
||||||
|
tracing = false;
|
||||||
|
statsFresh = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeStats() {
|
||||||
|
if (statsFresh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(times);
|
||||||
|
|
||||||
|
min = Long.MAX_VALUE;
|
||||||
|
max = -1;
|
||||||
|
mean = 0;
|
||||||
|
for (long f: times) {
|
||||||
|
mean += f;
|
||||||
|
if (f < min) {
|
||||||
|
min = f;
|
||||||
|
}
|
||||||
|
if (f > max) {
|
||||||
|
max = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mean /= times.size();
|
||||||
|
|
||||||
|
variance = 0;
|
||||||
|
for (long f: times) {
|
||||||
|
variance += (f-mean)*(f-mean);
|
||||||
|
}
|
||||||
|
variance /= times.size();
|
||||||
|
stddev = (long) Math.sqrt((double) variance);
|
||||||
|
|
||||||
|
p10 = times.get(times.size()*10/100);
|
||||||
|
p50 = times.get(times.size()*50/100);
|
||||||
|
p90 = times.get(times.size()*90/100);
|
||||||
|
|
||||||
|
statsFresh = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
computeStats();
|
||||||
|
return String.format(
|
||||||
|
"%s:\n" +
|
||||||
|
"| %d samples\n" +
|
||||||
|
"| Mean %.3f\u00B1%.3fms\n" + // plusminus
|
||||||
|
"| Min %.3fms ; Max %.3fms\n" +
|
||||||
|
"| p10 %.3fms ; p50 %.3fms ; p90 %.3fms\n" +
|
||||||
|
"%s",
|
||||||
|
name,
|
||||||
|
times.size(),
|
||||||
|
mean/10e6,
|
||||||
|
stddev/10e6,
|
||||||
|
min/10e6,
|
||||||
|
max/10e6,
|
||||||
|
p10/10e6,
|
||||||
|
p50/10e6,
|
||||||
|
p90/10e6,
|
||||||
|
makeGraph());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String makeGraph() {
|
||||||
|
char canvas[][] = new char[GRAPH_HEIGHT][GRAPH_WIDTH];
|
||||||
|
for (int i = 0; i < GRAPH_HEIGHT; i++)
|
||||||
|
for (int j = 0; j < GRAPH_WIDTH; j++)
|
||||||
|
canvas[i][j] = ' ';
|
||||||
|
|
||||||
|
long bucketSize = (p90 - p10) / GRAPH_WIDTH+1;
|
||||||
|
int bucketCount[] = new int[GRAPH_WIDTH];
|
||||||
|
for (long time : times) {
|
||||||
|
if (time<p90 && time>p10) {
|
||||||
|
bucketCount[(int) ((time - p10) / bucketSize)]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxBucket = 0;
|
||||||
|
for (int i = 0; i < GRAPH_WIDTH; i++)
|
||||||
|
if (bucketCount[i] > maxBucket) {
|
||||||
|
maxBucket = bucketCount[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < GRAPH_HEIGHT; i++)
|
||||||
|
for (int j = 0; j < GRAPH_WIDTH; j++)
|
||||||
|
if (i < bucketCount[j] * GRAPH_HEIGHT / maxBucket) {
|
||||||
|
canvas[i][j] = 'Z';
|
||||||
|
}
|
||||||
|
|
||||||
|
String graph = new String();
|
||||||
|
for (int i = 0; i < GRAPH_HEIGHT; i++)
|
||||||
|
{
|
||||||
|
int percentage = 100 * (GRAPH_HEIGHT - i - 1) * maxBucket / (times.size() * GRAPH_HEIGHT);
|
||||||
|
graph += String.format("| %2d%% ", percentage);
|
||||||
|
for (int j = 0; j < GRAPH_WIDTH; j++)
|
||||||
|
graph += canvas[GRAPH_HEIGHT-1-i][j];
|
||||||
|
graph += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
graph += "| p10";
|
||||||
|
for (int i = 0; i < GRAPH_WIDTH-6; i++)
|
||||||
|
graph += " ";
|
||||||
|
graph += "p90\n";
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dumps the collected times to a file on the device. This allows us to grab the raw data
|
||||||
|
* and perform more in-depth analysis.
|
||||||
|
*/
|
||||||
|
public void dump(Context context) {
|
||||||
|
String state = Environment.getExternalStorageState();
|
||||||
|
if (!Environment.MEDIA_MOUNTED.equals(state)) {
|
||||||
|
Log.e("YogaLayoutBenchmark","No external file storage");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
String filename = format.format(new Date()) + "_" + name.replace(' ','_');
|
||||||
|
File file = new File(context.getExternalFilesDir(
|
||||||
|
Environment.DIRECTORY_DOCUMENTS), filename);
|
||||||
|
|
||||||
|
try {
|
||||||
|
PrintWriter printWriter = new PrintWriter(file);
|
||||||
|
for (long l : times) {
|
||||||
|
printWriter.println(l);
|
||||||
|
}
|
||||||
|
printWriter.close();
|
||||||
|
|
||||||
|
Log.i("YogaLayoutBenchmark","Benchmark data saved in "+file.getPath());
|
||||||
|
} catch (java.io.IOException e) {
|
||||||
|
Log.e("YogaLayoutBenchmark", "Could not save benchmark data", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewParent;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
import com.facebook.yoga.android.YogaLayout;
|
||||||
|
|
||||||
|
public class BenchmarkFragment extends Fragment implements AdapterView.OnItemSelectedListener {
|
||||||
|
private LayoutInflater mInflater;
|
||||||
|
|
||||||
|
protected com.facebook.yoga.android.YogaLayout rootLayout;
|
||||||
|
protected int yogaLayout;
|
||||||
|
protected int linearLayout;
|
||||||
|
|
||||||
|
static final Random random = new Random();
|
||||||
|
|
||||||
|
static void randomizeText(View root) {
|
||||||
|
if (root instanceof TextView) {
|
||||||
|
((TextView) root).setText("" + random.nextInt(1000));
|
||||||
|
((TextView) root).setTextSize(10 + random.nextInt(20));
|
||||||
|
ViewParent parent = root.getParent();
|
||||||
|
if (parent instanceof YogaLayout) {
|
||||||
|
((YogaLayout) parent).invalidate(root);
|
||||||
|
}
|
||||||
|
} else if (root instanceof ViewGroup) {
|
||||||
|
for (int i = 0; i < ((ViewGroup) root).getChildCount(); i++) {
|
||||||
|
randomizeText(((ViewGroup) root).getChildAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BenchmarkFragment() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(
|
||||||
|
LayoutInflater inflater,
|
||||||
|
ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
mInflater = inflater;
|
||||||
|
|
||||||
|
rootLayout = (YogaLayout) inflater.inflate(
|
||||||
|
R.layout.benchmark_fragment,
|
||||||
|
container,
|
||||||
|
false);
|
||||||
|
|
||||||
|
Spinner benchmarkSelect = (Spinner) rootLayout.findViewById(R.id.benchmarkSelect);
|
||||||
|
String[] items = new String[]{"Basic", "Typical", "Nested"};
|
||||||
|
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_dropdown_item, items);
|
||||||
|
benchmarkSelect.setAdapter(adapter);
|
||||||
|
benchmarkSelect.setOnItemSelectedListener(this);
|
||||||
|
return rootLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
|
||||||
|
switch (pos) {
|
||||||
|
case 0:
|
||||||
|
yogaLayout = R.layout.benchmark_layout_1;
|
||||||
|
linearLayout = R.layout.benchmark_layout_1_linear;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
yogaLayout = R.layout.benchmark_layout_2;
|
||||||
|
linearLayout = R.layout.benchmark_layout_2_linear;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
yogaLayout = R.layout.benchmark_layout_3;
|
||||||
|
linearLayout = R.layout.benchmark_layout_3_linear;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
updatePreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
yogaLayout = R.layout.benchmark_layout_1;
|
||||||
|
linearLayout = R.layout.benchmark_layout_1_linear;
|
||||||
|
updatePreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePreview() {
|
||||||
|
LinearLayout previewLayout = (LinearLayout) rootLayout.findViewById(R.id.preview);
|
||||||
|
View v = mInflater.inflate(yogaLayout, rootLayout, false);
|
||||||
|
v.setLayoutParams(new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT));
|
||||||
|
previewLayout.removeAllViews();
|
||||||
|
previewLayout.addView(v);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.util.Log;
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
|
||||||
|
public class BenchmarkInflate extends BenchmarkFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(
|
||||||
|
LayoutInflater inflater,
|
||||||
|
ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
|
||||||
|
Button b = (Button) rootLayout.findViewById(R.id.btn);
|
||||||
|
b.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
startBenchmark();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rootLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startBenchmark() {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||||
|
TextView textView = (TextView) rootLayout.findViewById(R.id.text);
|
||||||
|
|
||||||
|
final int ITERATIONS = 500;
|
||||||
|
|
||||||
|
inflater.inflate(yogaLayout, null);
|
||||||
|
inflater.inflate(linearLayout, null);
|
||||||
|
|
||||||
|
BenchmarkAggregator yogaInflationAggregator = new BenchmarkAggregator("Yoga Inflate");
|
||||||
|
BenchmarkAggregator linearInflationAggregator = new BenchmarkAggregator("Linear Inflate");
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
yogaInflationAggregator.startTrace();
|
||||||
|
inflater.inflate(yogaLayout, null);
|
||||||
|
yogaInflationAggregator.endTrace();
|
||||||
|
linearInflationAggregator.startTrace();
|
||||||
|
inflater.inflate(linearLayout, null);
|
||||||
|
linearInflationAggregator.endTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
textView.setText(
|
||||||
|
yogaInflationAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearInflationAggregator.toString());
|
||||||
|
Log.i(
|
||||||
|
"YogaLayoutBenchmark",
|
||||||
|
yogaInflationAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearInflationAggregator.toString());
|
||||||
|
rootLayout.invalidate();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BenchmarkLayout extends BenchmarkFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(
|
||||||
|
LayoutInflater inflater,
|
||||||
|
ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
|
||||||
|
Button b = (Button) rootLayout.findViewById(R.id.btn);
|
||||||
|
b.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
startBenchmark();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rootLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startBenchmark() {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||||
|
TextView textView = (TextView) rootLayout.findViewById(R.id.text);
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
final int ITERATIONS = 500;
|
||||||
|
|
||||||
|
BenchmarkAggregator yogaInflationAggregator = new BenchmarkAggregator("Yoga Layout");
|
||||||
|
BenchmarkAggregator linearInflationAggregator = new BenchmarkAggregator("Linear Layout");
|
||||||
|
View yogaView = inflater.inflate(yogaLayout, null);
|
||||||
|
View linearView = inflater.inflate(linearLayout, null);
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
randomizeText(yogaView);
|
||||||
|
randomizeText(linearView);
|
||||||
|
yogaView.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY));
|
||||||
|
linearView.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY));
|
||||||
|
yogaInflationAggregator.startTrace();
|
||||||
|
yogaView.layout(0, 0, yogaView.getMeasuredWidth(), yogaView.getMeasuredHeight());
|
||||||
|
yogaInflationAggregator.endTrace();
|
||||||
|
linearInflationAggregator.startTrace();
|
||||||
|
linearView.layout(0, 0, linearView.getMeasuredWidth(), linearView.getMeasuredHeight());
|
||||||
|
linearInflationAggregator.endTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
textView.setText(
|
||||||
|
yogaInflationAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearInflationAggregator.toString());
|
||||||
|
Log.i(
|
||||||
|
"YogaLayoutBenchmark",
|
||||||
|
yogaInflationAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearInflationAggregator.toString());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BenchmarkMeasure extends BenchmarkFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(
|
||||||
|
LayoutInflater inflater,
|
||||||
|
ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
|
||||||
|
Button b = (Button) rootLayout.findViewById(R.id.btn);
|
||||||
|
b.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
startBenchmark();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rootLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startBenchmark() {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||||
|
TextView textView = (TextView) rootLayout.findViewById(R.id.text);
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
final int ITERATIONS = 500;
|
||||||
|
|
||||||
|
BenchmarkAggregator yogaMeasureAggregator = new BenchmarkAggregator("Yoga Measure");
|
||||||
|
BenchmarkAggregator linearMeasureAggregator = new BenchmarkAggregator("Linear Measure");
|
||||||
|
View yogaView = inflater.inflate(yogaLayout, null);
|
||||||
|
View linearView = inflater.inflate(linearLayout, null);
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
randomizeText(yogaView);
|
||||||
|
randomizeText(linearView);
|
||||||
|
yogaMeasureAggregator.startTrace();
|
||||||
|
yogaView.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY));
|
||||||
|
yogaMeasureAggregator.endTrace();
|
||||||
|
linearMeasureAggregator.startTrace();
|
||||||
|
linearView.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY));
|
||||||
|
linearMeasureAggregator.endTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
textView.setText(
|
||||||
|
yogaMeasureAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearMeasureAggregator.toString());
|
||||||
|
Log.i(
|
||||||
|
"YogaLayoutBenchmark",
|
||||||
|
yogaMeasureAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearMeasureAggregator.toString());
|
||||||
|
|
||||||
|
yogaMeasureAggregator.dump(getActivity());
|
||||||
|
linearMeasureAggregator.dump(getActivity());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.Menu;
|
||||||
|
|
||||||
|
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 AppCompatActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
LayoutInflater.from(this).setFactory(YogaViewLayoutFactory.getInstance());
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
SoLoader.init(this, false);
|
||||||
|
|
||||||
|
setContentView(R.layout.main_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.action_bar_home, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
// There is only one option
|
||||||
|
Intent intent = new Intent(this, BenchmarkActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
this.finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
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>
|
50
android/sample/res/layout/benchmark_fragment.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<YogaLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:yoga="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/rt"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_height="50dp"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="Run benchmark"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/benchmarkSelect"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:spinnerMode="dropdown"
|
||||||
|
/>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="2dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/preview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
30
android/sample/res/layout/benchmark_layout_1.xml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<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="60dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_flex="0"
|
||||||
|
yoga:yg_marginAll="5dp"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
yoga:yg_flex="0"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_2_text"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
yoga:yg_marginHorizontal="5dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
28
android/sample/res/layout/benchmark_layout_1_linear.xml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
android:layout_marginRight="5dp"
|
||||||
|
android:text="@string/child_2_text"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
104
android/sample/res/layout/benchmark_layout_2.xml
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<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="60dp"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:height="40dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginAll="10dp"
|
||||||
|
yoga:yg_aspectRatio="1"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:height="40dp"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
yoga:yg_justifyContent="space_around"
|
||||||
|
>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:height="8dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_aspectRatio="1"
|
||||||
|
/>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:height="8dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_aspectRatio="1"
|
||||||
|
/>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:height="8dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_aspectRatio="1"
|
||||||
|
/>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</YogaLayout>
|
96
android/sample/res/layout/benchmark_layout_2_linear.xml
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<LinearLayout
|
||||||
|
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="60dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="8dp"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="8dp"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="8dp"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
206
android/sample/res/layout/benchmark_layout_3.xml
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<YogaLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:yoga="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_justifyContent="center"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</YogaLayout>
|
204
android/sample/res/layout/benchmark_layout_3_linear.xml
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
7
android/sample/res/layout/benchmark_select_layout.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<android.support.v4.view.ViewPager
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/viewpager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
/>
|
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/com.facebook.samples.yoga"
|
||||||
|
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:yg_marginHorizontal="10dp"
|
||||||
|
yoga:yg_marginTop="5dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
yoga:yg_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:yg_flex="1"
|
||||||
|
yoga:yg_marginStart="8dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
||||||
|
<YogaLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/sample_children_background"
|
||||||
|
yoga:yg_marginHorizontal="10dp"
|
||||||
|
yoga:yg_marginTop="5dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
yoga:yg_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:yg_flex="1"
|
||||||
|
yoga:yg_marginStart="8dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
||||||
|
<YogaLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/sample_children_background"
|
||||||
|
yoga:yg_marginHorizontal="10dp"
|
||||||
|
yoga:yg_marginTop="5dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
yoga:yg_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:yg_flex="1"
|
||||||
|
yoga:yg_marginStart="8dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
||||||
|
<YogaLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/sample_children_background"
|
||||||
|
yoga:yg_marginHorizontal="10dp"
|
||||||
|
yoga:yg_marginTop="5dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
yoga:yg_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:yg_flex="1"
|
||||||
|
yoga:yg_marginStart="8dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
||||||
|
<YogaLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/sample_children_background"
|
||||||
|
yoga:yg_marginHorizontal="10dp"
|
||||||
|
yoga:yg_marginTop="5dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
yoga:yg_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:yg_flex="1"
|
||||||
|
yoga:yg_marginStart="10dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
||||||
|
</YogaLayout>
|
19
android/sample/res/menu/action_bar_benchmark.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
>
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_home"
|
||||||
|
android:title="Home"
|
||||||
|
android:showAsAction="always"
|
||||||
|
/>
|
||||||
|
</menu>
|
19
android/sample/res/menu/action_bar_home.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
>
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_benchmark"
|
||||||
|
android:title="Benchmark"
|
||||||
|
android:showAsAction="always"
|
||||||
|
/>
|
||||||
|
</menu>
|
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>
|
14
android/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
|
||||||
|
This source code is licensed under the MIT license found in the
|
||||||
|
LICENSE file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<application/>
|
||||||
|
|
||||||
|
</manifest>
|
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.yoga.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;
|
||||||
|
import com.facebook.yoga.YogaNodeFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 = YogaNodeFactory.create();
|
||||||
|
|
||||||
|
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 = YogaNodeFactory.create();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|