Compare commits

...

182 Commits

Author SHA1 Message Date
Robert Spencer
17be6718ee Nicer formatting of gists in docs
Summary: The gists in the docs have large margins to fit with the front page.  This diff specialises that margin setting and sets it to something smaller for other gists.

Reviewed By: emilsjolander

Differential Revision: D4666016

fbshipit-source-id: 5121849a153e78d523b33e10b96641426e794f8d
2017-03-07 05:26:24 -08:00
Robert Spencer
abf912b729 Gradle version bump and POM details
Summary: This improves the quality of the published POM files, adding dependencies and marking the object as an 'aar'.  It also bumps the version to 1.2.0 for JCenter.

Reviewed By: emilsjolander

Differential Revision: D4620150

fbshipit-source-id: 968f1cea21af4b2f19aeff3f32ad575b185fa1bb
2017-03-07 03:56:46 -08:00
Eric Rozell
5bc0197c78 Workaround for P/Invoke AccessViolationException
Summary:
The issue is on ARM builds for Windows UWP. For the C# P/Invoke API wrapper, any native method that returns the YogaValue struct throws the AccessViolationException. The issue is not with structs in general, as returning the YogaSize / YGSize struct works fine. The issue seems to be limited to structs that have an enum member.

I tried a number of things to resolve the issue without changing the underlying native API for Windows. I read the ARM documentation and saw reference to variable enum sizes based on the number of enum members, so I tried to use a number of different UnmanagedType values in a [MarsalAs()] attribute on the enum member of the C# struct declaration.

What ultimately worked was to return a pointer to the location of the struct, and use the System.Runtime.InteropServices.PtrToStructure API to read the struct data from that pointer. I added a few new macros that will return the struct address on Windows only, other builds are not affected.

Note, I have not tested the impact of this ch
Closes https://github.com/facebook/yoga/pull/459

Reviewed By: emilsjolander

Differential Revision: D4652278

Pulled By: splhack

fbshipit-source-id: bf7ada4da1781e3f813b3ba331974b7bded476d9
2017-03-06 11:42:40 -08:00
Lukas Wöhrl
62f47190fb Added bool config to YGConfig to configure using web defaults
Summary:
Added bool config to YGConfig to configure using web defaults. See #445.
Closes https://github.com/facebook/yoga/pull/449

Reviewed By: astreet

Differential Revision: D4642272

Pulled By: emilsjolander

fbshipit-source-id: 4f35bd17b7f764f42295052a4a8b4ae46c192d7e
2017-03-03 10:55:59 -08:00
Lukas Wöhrl
a706f4c97c Mark all children as dirty if display changes
Summary:
If we set ```display:none``` all children are set with layout sizes/values of 0. We need do mark all those children as dirty to force a relayout if we toggle the display on a higher parent node. This fixes #443
Closes https://github.com/facebook/yoga/pull/448

Reviewed By: astreet

Differential Revision: D4642273

Pulled By: emilsjolander

fbshipit-source-id: dfdb920e2049952bd6c7f48cfa53b1448e1f3e8f
2017-03-03 10:45:19 -08:00
Lukas Wöhrl
feb365a77b Explicitly set new experimental and a small other improvement
Summary:
This sets the new ```YGExperimentalFeatureMinFlexFix``` explicitly to false in the config.

It also a changes a stretch reason to reflect that it is the strech in a multiline.
Closes https://github.com/facebook/yoga/pull/447

Reviewed By: astreet

Differential Revision: D4642275

Pulled By: emilsjolander

fbshipit-source-id: 26777db7008ff6ee86da72ca9ea19e979b916cc9
2017-03-03 10:26:41 -08:00
Lukas Wöhrl
b2a4e67fee Use floats to prevent double calculation + float casting on scale
Summary:
Use ```float``` for calculation, as we would calculate with ```double``` and cast to float afterwards otherwise. So this removes the warning.
Closes https://github.com/facebook/yoga/pull/450

Reviewed By: astreet

Differential Revision: D4642267

Pulled By: emilsjolander

fbshipit-source-id: 184ef24474f2b8a42654a71a8e98839296648b2b
2017-03-03 10:26:40 -08:00
Emil Sjolander
e7d2792009 Add another nested percentage test
Summary: Add test covering a nested percentage container inside of a unconstraint container. This is something we ran into recently and want to make sure to cover in tests.

Reviewed By: astreet

Differential Revision: D4637519

fbshipit-source-id: a8fe3c7702c2ea0ad954cce80fbdf953bb23c997
2017-03-03 10:26:40 -08:00
Emil Sjolander
0fde1424f0 re-generate tests. Something was missed when rebasing
Summary: Some of the tests were not generated correctly. most likely due to a rebase.

Reviewed By: astreet

Differential Revision: D4637539

fbshipit-source-id: 196478d7e5197519af9ab05e5134e6fb7d22b992
2017-03-03 10:26:40 -08:00
Robert Spencer
29fd447f0c Margin percent values should be floats
Summary: Percentages should be floats

Reviewed By: emilsjolander

Differential Revision: D4642511

fbshipit-source-id: f1ef78259cf967acec9b82d77e43d7b9ad263e5b
2017-03-03 06:48:10 -08:00
Robert Spencer
7047d96087 Add yg prefix to attributes
Summary: To avoid clashes in the `app:` namespace, we prefix all yoga attributes with `yg_`.

Reviewed By: emilsjolander

Differential Revision: D4643080

fbshipit-source-id: 3e9265fd57e56a1df2f687a5d17c5bc66b8befa3
2017-03-03 00:41:04 -08:00
Robert Spencer
6336e641f4 Add ability to invalidate views
Summary: When some drawing attributes of a view changes how it measures, we need to be able to relayout it correctly.  This adds method `invalidate(View)` to `YogaLayout` which will flag the corresponding node as dirty and requiring layout again.

Reviewed By: emilsjolander

Differential Revision: D4634563

fbshipit-source-id: af7f47dce00a31414d0987a58307c5d44c1bcf20
2017-03-02 02:58:52 -08:00
Scott Wolchok
ecabe757a2 BUCK file renaming round 2 (13/13)
Summary: Ran the autoformat linter on our BUCK files.

Reviewed By: dinhviethoa

Differential Revision: D4641344

fbshipit-source-id: 25b42543ddf5cc60c72e4228cec1c5175f60eaca
2017-03-01 20:42:23 -08:00
Lukas Wöhrl
37c48257ae Move configuration to new YGConfig and pass them down to CalculateLayout
Summary:
Move configuration to new ```YGConfig``` and pass them down to CalculateLayout. See #418 .

Adds ```YGConfigNew()``` + ```YGConfigFree```, and changed ```YGSetExperimentalFeatureEnabled``` to use the config.

New function for calculation is ```YGNodeCalculateLayoutWithConfig```.
Closes https://github.com/facebook/yoga/pull/432

Reviewed By: astreet

Differential Revision: D4611359

Pulled By: emilsjolander

fbshipit-source-id: a1332f0e1b21cec02129dd021ee57408449e10b0
2017-03-01 09:27:53 -08:00
Emil Sjolander
8668e43f6d Fix margin auto for start and end values
Summary: Margin auto was not handling start/end margins correctly

Reviewed By: astreet

Differential Revision: D4627339

fbshipit-source-id: eebf64e79a34331e79cffcfa3662d4938fbd6c13
2017-03-01 09:27:52 -08:00
Emil Sjolander
785713c9c0 default root node to size of parent contraints
Summary: This is a follow up on a recent change which made the constraints passed into conculateLayout describe the parent constraints and not the root node constraints. This broke some assumptions and was not very inuitive if no size was set on the root. Therefor this diff ensure that if the root node does not have any size set then it will adopt the size of the parent constraints.

Reviewed By: dshahidehpour

Differential Revision: D4634616

fbshipit-source-id: 089eb4313c5bb810a6ff56f158cd19cec71808ec
2017-03-01 07:11:25 -08:00
Robert Spencer
b523402eda Update NDK version to 12
Summary: This diff updates the NDK version from 10 to 12

Reviewed By: emilsjolander

Differential Revision: D4634938

fbshipit-source-id: 6a9cbc48dbcbda4674d6460120c7a0d8abd626ab
2017-03-01 06:27:17 -08:00
Emil Sjolander
3790635af1 Re-generate wrap tests
Summary: Seems someone forgot to run the generation script

Reviewed By: astreet

Differential Revision: D4627337

fbshipit-source-id: 17dd1e1fed938a049ae820a9a4ac913667073d09
2017-03-01 06:27:16 -08:00
Robert Spencer
b940fadb7e Add android bindings to margin:auto
Summary: [This commit](1146013e9e) (or diff D4501142) adds an `auto` option for margins.  This diff allows you to leverage that in android via attribute `yoga:margin_all="auto"` (and as expected for the other edges).

Reviewed By: emilsjolander

Differential Revision: D4634684

fbshipit-source-id: 158f70ec975b5bb3a666e590b76eb52daeb38f49
2017-03-01 05:57:03 -08:00
Georgiy Kassabli
3ef2970032 Yoga test failure for flexing with min stack dimension
Summary: Test fails when we have flexible child and min/max layout dimension. Yoga should flex the child to minimal size, while in reality Yoga flexes it to maximal size

Reviewed By: emilsjolander

Differential Revision: D4558653

fbshipit-source-id: 06b38d7ed43aee063cc881f38b84558641f043f3
2017-02-28 16:28:54 -08:00
Robert Spencer
4372aa16d3 Enable RTL on sample app
Summary: The manifest didn't acknowledge that the sample app supports RTL.  Thus `TextView`s didn't render properly.

Reviewed By: emilsjolander

Differential Revision: D4628867

fbshipit-source-id: 72e57f48f7d68a8d2d6dd091b44b9452a3fe281a
2017-02-28 12:27:15 -08:00
Lukas Wöhrl
3346f9511a Change flex getters to return the set values
Summary:
Changed the flex getters to return the values they were actually set. See #421 .
Closes https://github.com/facebook/yoga/pull/431

Reviewed By: astreet

Differential Revision: D4604744

Pulled By: emilsjolander

fbshipit-source-id: 02d79100ef22be866db1c3bd9d53e4447186811f
2017-02-28 09:26:32 -08:00
Emil Sjolander
1cd7363bea Pass the parent size to YGNodeCalculateLayout instead of the node size
Summary: The size of the node is already set on the node however there was no way to set the size of the parent to the root so that the root could use percentages. This change fixes this by making the width and height passed to calculate layout be the width and height of the hypothetical parent.

Reviewed By: astreet

Differential Revision: D4611417

fbshipit-source-id: 2fb0eedffa17f0ec89b601722a1717a72e216b9e
2017-02-28 08:11:58 -08:00
Lukas Wöhrl
17e3dca9f9 Fix percentage in flexing parent
Summary:
If we don't measure exactly, percentage values aren't exactly either. Fix for #414.
Closes https://github.com/facebook/yoga/pull/416
Closes https://github.com/facebook/yoga/pull/414

Reviewed By: astreet

Differential Revision: D4604729

Pulled By: emilsjolander

fbshipit-source-id: 66880230073209cbe89668b838c2a82e7f9b34df
2017-02-28 07:12:05 -08:00
Robert Spencer
533f560ce0 Android bindings for display property
Summary: Diff D4501141 added display attributes for Yoga.  This exposes them in the android library.

Reviewed By: emilsjolander

Differential Revision: D4605574

fbshipit-source-id: dbad3d6fe924682c6b81f65bbba9727085de2d81
2017-02-28 00:26:27 -08:00
Robert Spencer
6a60d4893e Add travis_wait to installing Android SDK in travis builds
Summary: The android sdk and api installation seems to be timing out on Travis.  This should extend the 10 minute limit to 20 minutes.  Hopefully this will be enough to download it all.  If not, we must just extend the timeout.

Reviewed By: emilsjolander

Differential Revision: D4588245

fbshipit-source-id: fef25c54b081ba4d96d1e0435c6c1f643ff49b66
2017-02-28 00:26:27 -08:00
Emil Sjolander
51dd082682 bump javascript version
Summary: https://www.npmjs.com/package/yoga-layout

Reviewed By: arcanis

Differential Revision: D4611991

fbshipit-source-id: 4f75a85f8664e6d5bec609f6feb668a59f0fdde8
2017-02-27 01:13:08 -08:00
Michael Bolin
47d8d9d22b Apply auto-formatter for BUCK files in fbandroid.
Summary:
For more background, see:

https://fb.facebook.com/groups/303159406399348/permalink/1334977403217538/
https://fburl.com/auto-format-build-files
D4527873

fbshipit-source-id: 278ce6f67f5df830b2218e3aca69be103d3c56a6
2017-02-24 21:44:02 -08:00
Dustin Shahidehpour
d6d4dcb141 Update YogaKitSample Podfile.lock
Summary: #accept2ship

Reviewed By: amonshiz

Differential Revision: D4614473

fbshipit-source-id: d46fc54c53280fca1607dc75b59e730f340eb4e7
2017-02-24 14:26:55 -08:00
Georgiy Kassabli
37ec1774a7 Add rounding to the pixel grid to Yoga
Summary: This diff adds rounding to the pixel grid feature to Yoga and appropriate property

Reviewed By: emilsjolander

Differential Revision: D4565980

fbshipit-source-id: 9700f6d6ed147f82b19f230fbff2e9ccbd625b25
2017-02-24 09:57:00 -08:00
birfincankafein
3ad4d7dd6e Solve build target error while building Android with Buck.
Summary:
SoLoader library targets Android API 21 but main manifest targets 19. This will block buck android build.
Closes https://github.com/facebook/yoga/pull/437

Reviewed By: astreet

Differential Revision: D4611364

Pulled By: emilsjolander

fbshipit-source-id: 113bcfce751e98b8a42e46e0101b6a4b1327b9c3
2017-02-24 03:26:46 -08:00
Emil Sjolander
e596091fa2 Bump podspec versions
Summary: podspec version bump

Reviewed By: dshahidehpour

Differential Revision: D4606652

fbshipit-source-id: a9a7d4512f174182301a0b7ac2ae13303b659a3f
2017-02-23 11:57:06 -08:00
Lukas Wöhrl
4f5c7ed6af Fix align-content:strech overriding align-item
Summary:
Fix for #413. This was a hangover from a previous attept to fix other align-content problems.
Closes https://github.com/facebook/yoga/pull/417

Reviewed By: astreet

Differential Revision: D4604727

Pulled By: emilsjolander

fbshipit-source-id: 92fd31a385d8182c6b201c891d5ae478372d525d
2017-02-23 08:31:05 -08:00
Robert Spencer
60ffa1953b Gradle for android library
Summary: Adds a buildscript for gradle as well as bintray upload capabilities for the YogaLayout library

Reviewed By: emilsjolander

Differential Revision: D4604712

fbshipit-source-id: bacbcc20b7ed6ee8689130287a48bd5d3826298c
2017-02-23 05:07:20 -08:00
Robert Spencer
5519a73087 Gradle for java library
Summary: This builds the java bindings with gradle, and adds a script for Facebook employees to upload the generated artifacts to JCenter.

Reviewed By: emilsjolander

Differential Revision: D4597335

fbshipit-source-id: 4c01695a8638000a417bfb49deba4b9b9b4e114b
2017-02-23 05:07:20 -08:00
Lukas Wöhrl
67717a7872 Force scalefactor=1 for gentest to fix issues with test generation on hdpi devices
Summary:
Since my new main work maschine is a hdpi device, all the gentests with rounding are producing different outputs.

This PR force the scalefactor=1 for gentest to fix issues with generation on hdpi devices.
Closes https://github.com/facebook/yoga/pull/434

Differential Revision: D4604724

Pulled By: emilsjolander

fbshipit-source-id: ce4036ae71a45775280e0504f20c06a4622ccceb
2017-02-23 01:26:55 -08:00
Aljoscha Meyer
4522d4b8aa Fix a typo in C API documentation
Summary:
Change "Certain nodes need *to* ability to measure themselves" to "Certain nodes need *the* ability to measure themselves".
Closes https://github.com/facebook/yoga/pull/430

Differential Revision: D4600091

Pulled By: emilsjolander

fbshipit-source-id: d20693b47291e79bd8c5f76e57d6dff2444333d2
2017-02-22 12:57:21 -08:00
Robert Spencer
d7ca339c27 Fix android height attribute
Summary: The attribute for height was incorrectly assumed to be type `float` which led to it not being explicitly defined.  It is actually a dimension.

Reviewed By: emilsjolander

Differential Revision: D4588629

fbshipit-source-id: 56c7e460d27528823944852d682e7f26bf908292
2017-02-21 00:12:09 -08:00
Emil Sjolander
6b39165801 Fix behaviour of wrapping container within align-items: not stretch
Summary: When a container's children wrap the container should match the parent size and not wrap to the new size of the children. This is confirmed behavior in chrome.

Reviewed By: astreet

Differential Revision: D4578614

fbshipit-source-id: 5d22a3a673735587384d775189158a87bb1d457d
2017-02-20 07:28:42 -08:00
Maël Nison
78ade6cfb5 Improve JS Travis testing
Summary:
Build emscripten js file on travis
Closes https://github.com/facebook/yoga/pull/397

Reviewed By: arcanis

Differential Revision: D4579563

Pulled By: emilsjolander

fbshipit-source-id: fa5f92fd26f758fb617e428c07aabf2dccd63b37
2017-02-20 05:41:38 -08:00
Robert Spencer
3f68b4f76b Travis install android sdk and api for build
Summary:
Travis android build is failing with

    BUILD FAILED: Google APIs not found in /usr/local/opt/android-sdk/add-ons/addon-google_apis-google-19/libs.
    Please run '/usr/local/opt/android-sdk/tools/android sdk' and select both 'SDK Platform' and 'Google APIs' under Android (API 19)

This should fix that error

Reviewed By: emilsjolander

Differential Revision: D4588053

fbshipit-source-id: e57d635141e8aede5803b919ee5a28a60c5e667c
2017-02-20 02:26:16 -08:00
Robert Spencer
521aab5fcc Omptimisation on layout and measure children of YogaLayout
Summary:
You must measure children before you lay them out, and YogaLayout didn't do this.  This fixes that.

We also only recompute the yoga tree if the YogaLayout is laid out with a different size to what it's been measured as.

Reviewed By: emilsjolander

Differential Revision: D4572237

fbshipit-source-id: 6e86dbf939b06338c1dc2a37b7dafafd548dd390
2017-02-19 23:58:09 -08:00
Rui Marinho
42492596b3 Changes for nuget and CI support
Summary:
For now i setup the CI using VSTS (Visual Studio Team Services) , i m using my own account, but i want to move this to a Travis setup so it would be easy ported to Facebook own build system. We can also take a look on how buck can help with this.

Here's a overview of my dashboard for the build and release process on VSTS:

<img width="1084" alt="screen shot 2017-02-16 at 23 52 07" src="https://cloud.githubusercontent.com/assets/1235097/23046869/ff4dcada-f4a3-11e6-8d09-fb8974fb58d4.png">

The all process is pretty simple, there's a few tricks here and there, but the basic steps are:

<img width="1036" alt="builds" src="https://cloud.githubusercontent.com/assets/1235097/23046874/0cb95fc2-f4a4-11e6-8fd8-3048be7ffd9d.png">

These run for every commit and publish the artifacts, then the release lane takes that artifacts and builds a nuget, after that (and it's not implemented yet) we run UI Tests on devices Android , iOS for the nuget created and run tests on UWP and .net45 on both windows and OS X so
Closes https://github.com/facebook/yoga/pull/408

Reviewed By: emilsjolander

Differential Revision: D4576542

Pulled By: splhack

fbshipit-source-id: 66e0e4c1cb3721ed7aa7118e4e226b6ec575fea8
2017-02-17 10:41:47 -08:00
Eric Rozell
b24e728666 Adds UWP build for yoga.dll
Summary:
The existing Yoga.vcxproj works great for Desktop apps, but breaks when you try to use the resulting DLL on mobile, Xbox, etc. This change compiles the DLL for the UWP and the Windows Store.
Closes https://github.com/facebook/yoga/pull/401

Reviewed By: emilsjolander

Differential Revision: D4561354

Pulled By: splhack

fbshipit-source-id: 643ad4ed1ffc73719d35974e2d357c37d5b1d1c4
2017-02-16 11:42:30 -08:00
Kazuki Sakamoto
4fe0b810e1 Fix callbacks on AOT
Summary:
Based on the idea of #386 by rmarinho
Closes https://github.com/facebook/yoga/pull/388

Reviewed By: emilsjolander

Differential Revision: D4570778

Pulled By: splhack

fbshipit-source-id: 362983deaf6f040c42b3db8205b711e7e5e60eaf
2017-02-16 11:15:36 -08:00
Rui Marinho
8deed174f5 Fix callbacks on AOT
Summary:
When using AOT mode on Mono one can't use instance methods for callbacks, the compiler needs the MonoPInvokeCallback attribute on a static method to know how to get back to the managed world.
This worked fine without the change in JIT mode.

I not sure if we should use a __MONO__ flag for this stuff as this could be needed for other usage that not only on iOS.

~~The adicional change is that one should as good practice call Dispose on the YogaNode when using callbacks to make sure we remove the handler from our dictionary, i was trying to write a test for this.. but i saw TestMeasureFuncWithDestructor was already there, but it doesn't seem correct to me, can you check splhack.~~
Closes https://github.com/facebook/yoga/pull/386

Reviewed By: emilsjolander

Differential Revision: D4546030

Pulled By: splhack

fbshipit-source-id: 121d44a2ecd14d754b9614493db6ac15fca02da2
2017-02-16 11:15:36 -08:00
Kazuki Sakamoto
2184547094 Fix unit test for flexBasis
Summary: Fix unit test for flexBasis

Reviewed By: emilsjolander

Differential Revision: D4572394

fbshipit-source-id: ce0b3cd28b5c8a9910106308c561c95d1b3866e9
2017-02-16 10:26:33 -08:00
Lukas Wöhrl
8eda4dc040 Removed duplicate code by calculating with mainSize/crossSize
Summary:
This PR removes some duplicate code by calculating with ```mainSize```/```crossSize``` and converting that to ```width``` or ```height``` at the end. See #395 .
Closes https://github.com/facebook/yoga/pull/396

Reviewed By: astreet

Differential Revision: D4564713

Pulled By: emilsjolander

fbshipit-source-id: 0b24e69cc9dc75cdf93deeb6c076dcacf134c6d8
2017-02-16 07:41:32 -08:00
Kazuki Sakamoto
4d4db92a46 Fix unit test
Summary: Fix #406 #407

Reviewed By: emilsjolander

Differential Revision: D4569680

fbshipit-source-id: a7b78674ed483d8619bd4aaa6e463203ef619c9b
2017-02-16 07:41:32 -08:00
Emil Sjolander
ea8b7e0c91 Fix up some small issues with YGUnitAuto
Summary: There are still some pieces of RN which does not handle YGUnitAuto and makes use of either the value being nan or the unit being undefined. This diff makes this more robust to those kinds of situations.

Reviewed By: wwjholmes

Differential Revision: D4567045

fbshipit-source-id: ace5fd89bd534a6bb5ec7dba0c3afbf13d62d7c9
2017-02-16 06:58:47 -08:00
Robert Spencer
6928957096 Set ANDROID_SDK and ANDROID_HOME for Travis build
Summary: Travis builds are failing due to ANDROID_SDK not being set.  So we set both it and ANDROID_HOME to where homebrew should have created a link to the installation.

Reviewed By: emilsjolander

Differential Revision: D4571703

fbshipit-source-id: a6dc4eb07006dc8baefb6ca938111ff256c6f018
2017-02-16 02:58:45 -08:00
Robert Spencer
b680b726d1 Add Android Travis badge to README.md
Summary: Adds the Travis build badge for the android target to the README.md

Reviewed By: emilsjolander

Differential Revision: D4571693

fbshipit-source-id: a5110dac7d86989cc4a14b858c63d59332072869
2017-02-16 02:44:53 -08:00
Robert Spencer
fbd692c449 Remove splash screen activity from sample app
Summary: The yoga splash screen that runs at the beginning of the app is unnecessary and can be removed for simplicty.

Reviewed By: emilsjolander

Differential Revision: D4571624

fbshipit-source-id: 3eb12f7c3447805f4546bd192df9670c5427572a
2017-02-16 02:44:50 -08:00
Kazuki Sakamoto
2199a7908d Fix BUCK
Summary:
- Deleted a non-existent include
- Fix #404

Reviewed By: bolinfest

Differential Revision: D4569377

fbshipit-source-id: 34161b28be8bab476b30442596314899463814ef
2017-02-15 16:58:04 -08:00
Dustin Shahidehpour
59704f1508 Backed out changeset 762168ced81e
Summary: Acting weird with Xcode 8.2.1

Differential Revision: D4567880

fbshipit-source-id: e5a200b59780ac3dd8f75b6152054778b9fc786c
2017-02-15 14:35:46 -08:00
Lukas Wöhrl
20536923d6 flex-wrap: wrap-reverse support
Summary:
I couldn't resist to do this 😄 #394

This adds ```flex-wrap: wrap-reverse```

I think we hit a edge case here:
https://stackoverflow.com/questions/33891709/when-flexbox-items-wrap-in-column-mode-container-does-not-grow-its-width

as is differs here from chrome, but I think that yoga is here more correct.

So I haven't added this test yet as this would fail against chrome, as chrome outputs a width of 30 for root, whereas yoga gets a width of 60 here, which I think is correct. Strangely the output of ```flex-wrap:wrap``` is in jsfiddle also only with a (visual) width of 30 on chrome, while the tests gets generated with 60.

```html
<div id="wrap_reverse_column" style="height: 100px; flex-wrap: wrap-reverse">
  <div style="height: 30px; width: 30px;"></div>
  <div style="height: 30px; width: 30px;"></div>
  <div style="height: 30px; width: 30px;"></div>
  <div style="height: 30px; width: 30px;"></div>
</div>
```

Looking forward what you think here emilsjolander
Closes https://github.com/facebook/yoga/pull/398

Reviewed By: astreet

Differential Revision: D4564711

Pulled By: emilsjolander

fbshipit-source-id: 33dc055abd8444b2aa7796ef90bd7ec99e961bb8
2017-02-15 13:42:47 -08:00
Lukas Wöhrl
bba7289537 Remove no longer valid limitiation hints
Summary:
Remove no longer valid limitiation hints, according to percentag, auto margins and flex values.
Closes https://github.com/facebook/yoga/pull/402

Reviewed By: astreet

Differential Revision: D4564709

Pulled By: emilsjolander

fbshipit-source-id: ef7f37921644b4d315c7a84552861713061b33e1
2017-02-15 08:26:56 -08:00
Dustin Shahidehpour
04d1ccc085 Create Xcode project so it's much easier to run tests.
Summary:
I don't even know how people have been running tests (unless they install BUCK). This creates a workspace to make it much easier to run tests.
Closes https://github.com/facebook/yoga/pull/400

Differential Revision: D4565290

Pulled By: dshahidehpour

fbshipit-source-id: 762168ced81e517126ac05c92bb27ccad0d9d305
2017-02-15 08:11:36 -08:00
Joel Marcey
a7e7c5eb52 Add actual Google Analytics ID
Summary:
We still had the default one from the template.
Closes https://github.com/facebook/yoga/pull/403

Reviewed By: astreet

Differential Revision: D4564708

Pulled By: emilsjolander

fbshipit-source-id: ec76325e0dca34f89e5a920627ced7fa812827de
2017-02-15 07:47:25 -08:00
David Hart
9d2839f8ca Rename YGUnitPixel to YGPoint...
Summary:
...to reflect the modern world we live in with dynamic DPI platforms :)
Closes https://github.com/facebook/yoga/pull/375

Reviewed By: dshahidehpour

Differential Revision: D4528518

Pulled By: emilsjolander

fbshipit-source-id: e422bd4ae148e02c598a7b484a6adfa8c0e1e0c9
2017-02-14 14:27:48 -08:00
Lukas Wöhrl
1146013e9e Feature auto margin
Summary:
Even so I know there are some opinions against ```margin: 0 auto``` it's still part of the spec: https://www.w3.org/TR/css-flexbox-1/#auto-margins and pretty usefull if you have to position via ```justify-content```.

This PR adds an implementation for that.

It adds an additonal ```YGUnitAuto``` and margins got ```YGNodeStyleSetMarginAuto``` functions as well.
Closes https://github.com/facebook/yoga/pull/357

Reviewed By: astreet

Differential Revision: D4501142

Pulled By: emilsjolander

fbshipit-source-id: 86519f8632496f46e78a7c9dbc5b21e212e3e0c7
2017-02-14 14:27:48 -08:00
Michael Bolin
8a91c0a0e5 Attempt to fix open source Yoga build.
Reviewed By: emilsjolander

Differential Revision: D4557733

fbshipit-source-id: b99701e9c1ec56fb147aa4cc738549df90aa7016
2017-02-14 10:45:02 -08:00
Emil Sjolander
a1c75454e9 Fix align-content strech with multiple lines
Summary: This is an update of facebook/yoga#368 which was reverted. It fixes support for align-content: strech with multiple lines. The problem with the last attempt at solving this was that align-items:stretch was interfering. We handle this now by detecting when the flex basis of the children hints at them overflowing. This is not 100% correct as the size of the items could change when remeasuring but it will work in 99% of cases.

Reviewed By: astreet

Differential Revision: D4551234

fbshipit-source-id: 2964f19cf415991dc55dfa2caa4868cb00c56bd0
2017-02-14 09:26:10 -08:00
Robert Spencer
ad3963daa6 Travis build of sample app
Summary: Build the sample app in travis

Reviewed By: emilsjolander

Differential Revision: D4558310

fbshipit-source-id: b730a7bc9036054a17c6204a93c63ea2064e0943
2017-02-14 08:41:42 -08:00
Robert Spencer
a66339d63c Separate YogaLayout library from sample app
Summary: The sample app has library-like elements (i.e. the `YogaLayout` and associated files).  This separates them out into a separate tree.

Reviewed By: emilsjolander

Differential Revision: D4558263

fbshipit-source-id: 33f8cec99661ef20e0e882663b554c12ae33c12f
2017-02-14 08:13:22 -08:00
Robert Spencer
d0bdd4dc91 Adds Android docs to landing page
Summary: Adds a simple "photo with poster and comment" layout to the landing page as an example for Android, along with the XML.

Reviewed By: emilsjolander

Differential Revision: D4558478

fbshipit-source-id: c7302321a67e99f5853358e711ff538d192f06e9
2017-02-14 08:13:22 -08:00
Robert Spencer
d24078be31 Move res files to be more gradle-esque
Summary: Resources don't usually live under the package name.  We want to gradle build this soon, so making the directory structure as traditional as possible is best.

Reviewed By: emilsjolander

Differential Revision: D4557978

fbshipit-source-id: 7f80599201fe007a895e52bc5141425f9a83eb51
2017-02-14 03:14:59 -08:00
Robert Spencer
f251648726 Add android docs
Summary: Adds docs for how to build the Android sample app and use the `YogaLayout`.

Reviewed By: emilsjolander

Differential Revision: D4557955

fbshipit-source-id: 49a3b8fde20de81a895244ffcecbd5bf392455b0
2017-02-14 02:48:14 -08:00
Emil Sjolander
b587ecb30f Fix travis builds
Summary: && instead of ; and only update xctools if needed

Reviewed By: passy

Differential Revision: D4558044

fbshipit-source-id: 90d55bf0147026e527b238365835d803a4bee7fb
2017-02-14 02:28:49 -08:00
Robert Spencer
a580712b2f Move in yoga sample android app
Summary: The sample app is simply moved into the repo.  A few libraries are included and the buck targets rearranged.

Reviewed By: emilsjolander

Differential Revision: D4528129

fbshipit-source-id: 3e9e779857cd9219711a939876c9275d75e09929
2017-02-14 00:11:38 -08:00
Michael Bolin
ce5d52b54e Update a number of build files in fbandroid/xplat to use the py_sdk build defs.
Summary:
I'm cleaning up these files in their own revision because I want to trigger
dirsync sandcastle separately from my other cleanup.

Reviewed By: mzlee

Differential Revision: D4549131

fbshipit-source-id: 1d45118256d8b517dea7a2b6c9e50bca1ccc1b0c
2017-02-13 22:26:31 -08:00
Dustin Shahidehpour
55fe6f0bc9 Add isDirty property and make markDirty less crashy/more performant.
Summary: For some internal Instagram diffs, and some external ones (auto-detection of dirty nodes). We need to give the dirty properties a little love. This adds a getter to find out if your node is dirty, and makes sure that the leaf node is properly setup before it is marked dirty to prevent a crash.

Reviewed By: emilsjolander

Differential Revision: D4549241

fbshipit-source-id: 36eda6fdb4ea7f968d126aab6da67896f4a01d40
2017-02-13 10:26:58 -08:00
Emil Sjolander
abf142ea3f Fix more travis file errors
Summary: and add badges to readme

Reviewed By: passy

Differential Revision: D4551571

fbshipit-source-id: c6eafe480e3667252eadc96c548c3b3c85046389
2017-02-13 09:41:35 -08:00
Dustin Shahidehpour
ae9f89b5d1 Add helper function for bulk updates.
Summary:
Currently, our configuration of Views looks like this:

```objc
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.isEnabled = YES;
view.yoga.height = 50;
view.yoga.width = 50;
```

Every time that we access `view.yoga` we have to access the associated object on `UIView` to get the `YGLayout`. This adds an extra `objc_msgSend` which increases binary size, and is slight perf impact.

This diff creates a way to modify the `YGLayout` with only a single `objc_msgSend`. Here's the new syntax:

```objc
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
[view configureLayoutWithBlock:^void(YGLayout *layout){
  layout.isEnabled = YES
  layout.height = 50;
  layout.width = 50;
}];
```

Here's the Swift version:
```swift
let view = UIView(frame: .zero)
view.configureLayout { (layout) in
  layout.isEnabled = true
  layout.height = 50
  layout.width = 50
}
```
Closes https://github.com/facebook/yoga/pull/393

Reviewed By: emilsjolander

Differential Revision: D4550382

Pulled By: dshahidehpour

fbshipit-source-id: 76d797d1e0de8e5dc767e02180a7fc440a70212e
2017-02-13 09:28:12 -08:00
Dustin Shahidehpour
058761e16e Give YogaKitSample some love, Convert it to a Swift Project
Summary:
To date, our sample project was lacking. There is still a lot of work that can be done to improve, but, this is a step in the right direction.

Here are the changes in this commit:
1. The project is written in Swift.
2. Created new CollectionView (via [IGListKit](https://github.com/instagram/iglistkit)), making it very easy to add new examples.
3. New examples for basic layouts, and including/excluding layouts on the fly.

Here's a video!

![](https://media.giphy.com/media/l0ExcvTLa0ADdawRa/giphy.gif)
Closes https://github.com/facebook/yoga/pull/392

Reviewed By: emilsjolander

Differential Revision: D4550379

Pulled By: dshahidehpour

fbshipit-source-id: 64a07acf96c1887f1d2ad0c54971fcedb64334a0
2017-02-13 09:13:43 -08:00
Kazuki Sakamoto
ad8c6225fd Build i386 for iOS and macOS
Summary: Closes https://github.com/facebook/yoga/pull/391

Reviewed By: emilsjolander

Differential Revision: D4549469

Pulled By: splhack

fbshipit-source-id: 7500b7235218f9a4f564adb36044303dff520fd6
2017-02-13 08:26:20 -08:00
Emil Sjolander
1cbadf5f54 Fix mistakes in travis file
Summary: Fix yaml errors

Reviewed By: passy

Differential Revision: D4551330

fbshipit-source-id: d17087cf51f9556c7015ea0fc4ab11fec44917f2
2017-02-13 06:56:27 -08:00
Emil Sjolander
e7021715b8 Split travis builds into multiple runs
Summary: Split travis into one run per language. This should improve build speed as well as improve signal as to what is failing.

Reviewed By: dshahidehpour

Differential Revision: D4551194

fbshipit-source-id: 36bc60193b4b287352073ab62a7bd053b15eaedf
2017-02-13 05:27:03 -08:00
Emil Sjolander
0d2749a3fd Revert D4528559: [yoga][PR] Fix align-content strech with multiple lines
Summary: This reverts commit 019e6f85fa452d0c3412f711e3886f0c4452da47

Differential Revision: D4528559

fbshipit-source-id: 4bd82b399cb36acb348f2c6fedcae6b360513424
2017-02-13 01:11:16 -08:00
Dustin Shahidehpour
76fbd628e1 Use correct rounding function when rounding pixels.
Summary: While debugging something at Instagram, I kept seeing a UILabel be truncated when it clearly had enough room to display all its' text. What I realized is that during our pixel rounding, we were losing precision because we were using the incorrect rounding function for floats. Changing from `round()` (which is for doubles) to `roundf()` fixed it.

Reviewed By: amonshiz

Differential Revision: D4549069

fbshipit-source-id: 78a1bb33e315e7c066b7fb625b1f5a28def76515
2017-02-11 19:56:08 -08:00
Dustin Shahidehpour
15309d2bdd Update README.md
Summary: Closes https://github.com/facebook/yoga/pull/389

Differential Revision: D4549243

Pulled By: dshahidehpour

fbshipit-source-id: 2c8d6d78af9f98994ad2f5f028494ae743c354b4
2017-02-11 14:12:51 -08:00
Dustin Shahidehpour
4f6924a0c1 BREAKING CHANGE: rename applyLayout to applyLayoutPreservingOrigin.
Summary: Will update on Monday

Reviewed By: emilsjolander

Differential Revision: D4545786

fbshipit-source-id: f8189d82f1c64cd1eac532fd2dfaa9aea35d6004
2017-02-11 11:26:07 -08:00
Lukas Wöhrl
063f65d065 Fix align-content strech with multiple lines
Summary:
Fixes ```align-content:strech``` on nodes without specified cross dimension, if there are multiple lines. Currently it uses the full height of the parent, but it has to use the line height. As we don't know the number of lines until here, we need to realign the relevant children.
Closes https://github.com/facebook/yoga/pull/368

Reviewed By: gkassabli

Differential Revision: D4528559

Pulled By: emilsjolander

fbshipit-source-id: 019e6f85fa452d0c3412f711e3886f0c4452da47
2017-02-11 08:41:45 -08:00
Lukas Wöhrl
adf8691093 Fix resolving bug on changing layout and optimized memory usage
Summary:
Due to the changes in 46817a38. We have a bug if the layout changes.

This PR fixes this bug and adds a test for it.

Additionally it correctly marks negative percentage values as undefined dim.

It also changes the ```resolvedDimensions``` to use a reference instead of the full value in order to minimize the memory requirement of a ```YGNode``` and reduces the copying of the ```YGValue```.
Closes https://github.com/facebook/yoga/pull/379

Reviewed By: gkassabli

Differential Revision: D4528552

Pulled By: emilsjolander

fbshipit-source-id: c024fe3a009c3788af319b689858ea3374c46477
2017-02-11 08:41:45 -08:00
Lukas Wöhrl
6a7ad2125d Add support for space-between and space-around on align-content
Summary:
Adds the two missing alignments ```space-between``` and ```space-around``` for ```align-content``` . Those values are a noop on ```align-items``` in order to prevent a breaking changes for an additional enum.

Fix #229
Closes https://github.com/facebook/yoga/pull/364

Reviewed By: gkassabli

Differential Revision: D4528561

Pulled By: emilsjolander

fbshipit-source-id: ea6291b6dd22cef05d9eec03893250d50371236e
2017-02-11 08:41:45 -08:00
Lukas Wöhrl
247aa26d3e Make enums.py c header output resistent to format.sh
Summary:
This PR changes the enums.py to create the header the same as format.sh would layout it. Reduces the clutter due to missed format.sh calls after enums.py generation.
Closes https://github.com/facebook/yoga/pull/380

Reviewed By: gkassabli

Differential Revision: D4529593

Pulled By: emilsjolander

fbshipit-source-id: 7281e0d500f79459c19cc8fe6dbc8fd77f0a537c
2017-02-11 08:41:45 -08:00
Dustin Shahidehpour
3c9f620c77 BREAKING CHANGE: Computed edge values are no longer returned on concrete properties, fix tests.
Summary:
Now that the Yoga library supports percentage values, the results returned from it's API were changed.

`YGNodeStyleGetPadding` returns the explicit value that you set, whereas `YGNodeLayoutGetPadding` returns the computed value. Since we are planning to build support for percentages, I'm modifying our API so that it strictly returns the value that was set. As a result:

```
view.yoga.margin = 10;

// view.yoga.margin == 10
// view.yoga.marginLeftWidth == 0
// view.yoga.marginRightWidth == 0
// etc.
```

Reviewed By: emilsjolander

Differential Revision: D4543471

fbshipit-source-id: a731025cd4b47e9f1a559c766494fc5a259291ae
2017-02-11 08:28:50 -08:00
Emil Sjolander
e0e2a61dfc Use Float.compare in java equals
Summary: Handles nans. Also if the unit is undefined there is no need to check the value.

Reviewed By: astreet

Differential Revision: D4531805

fbshipit-source-id: 723e15381e9fa39837a4c99f726501eda26af11b
2017-02-11 06:27:15 -08:00
Emil Sjolander
168ae4099d Always return undefined value if nothing is set
Summary: This reflects a check to native code where style values will always return the value that was set on them and default to undefined.

Reviewed By: astreet

Differential Revision: D4531779

fbshipit-source-id: 97a789e70dcf0fb5174e2039991e7a2b27f45f01
2017-02-11 06:27:12 -08:00
Emil Sjolander
6ceb4af2d4 Expose layout border to java
Summary: Expose layout border to java

Reviewed By: astreet

Differential Revision: D4543284

fbshipit-source-id: 6030915fc6f758e785a688f94c8ffbec7fbac8b8
2017-02-11 06:27:04 -08:00
Emil Sjolander
240c2dd657 Fix min/max not overriding width/height
Summary:
Two bugs:
1. Min/Max width/height should have higher priority than width/height
2. custom measure nodes percentages should be based in parent size like everything else.

Differential Revision: D4537576

fbshipit-source-id: c003f723f424afbca63170d41e54fd5ff837926d
2017-02-11 05:28:10 -08:00
Rui Marinho
a5b94ebd0c Add YogaDisplay to shared project
Summary: Closes https://github.com/facebook/yoga/pull/383

Reviewed By: emilsjolander

Differential Revision: D4537332

Pulled By: splhack

fbshipit-source-id: d3068fc09e567c9f175bdcc8974c8069575ef5f7
2017-02-10 11:13:24 -08:00
Dustin Shahidehpour
5037c2f365 Preserve the origin of the root view.
Summary: Currently, we have an issue in YogaKit where it ignores the preexisting bounds a root view. There are multiple fixes for this, but the easiest one for developer experience is to apply the preexisting bounds of the root view to it's frame after layout calculation.

Reviewed By: emilsjolander

Differential Revision: D4537173

fbshipit-source-id: ccef8b1c1398ea299b4e5710abe597378347a48d
2017-02-09 13:10:59 -08:00
Dustin Shahidehpour
ef05404bee Bump YogaKit podspec.
Summary: See commit message. #accept2ship

Reviewed By: emilsjolander

Differential Revision: D4536585

fbshipit-source-id: 808e39e7a38f470c67459a42686e095d8b5e5fc6
2017-02-09 08:46:30 -08:00
Dustin Shahidehpour
3db493665e Bump podspec version.
Summary: See commit message. #accept2ship

Reviewed By: emilsjolander

Differential Revision: D4536570

fbshipit-source-id: 4fc72bd4d9418ea06d24a6ca0cdd6845def30465
2017-02-09 08:26:17 -08:00
Emil Sjolander
737f1cc67c Remove now not needed definition of allow_unsafe_import
Summary: not needed any more

Reviewed By: bolinfest

Differential Revision: D4532533

fbshipit-source-id: 43b4db9a21ae774f7d41187e4e4598e171b7a59c
2017-02-09 03:27:11 -08:00
Georgiy Kassabli
b5c2b09780 Revert D4456312: Fix for Yoga test failure for flexing with min stack dimension
Summary: This reverts commit 82a39bc93cf3bf2374b968e9f7403397e752908e

Differential Revision: D4456312

fbshipit-source-id: 6b396f0a8b67619308456599377238b75d0c1ab3
2017-02-07 05:18:19 -08:00
Antonio Corrado
46817a38c3 Setting min=max dimension is treated as setting dimension
Summary: If a node has minDimension and maxDimension set at the same value, yoga will treat it as having a set dimension, doing less calculations.

Reviewed By: emilsjolander

Differential Revision: D4492395

fbshipit-source-id: 3f4293548399e006aa808b9586d24e77c7df1f21
2017-02-06 14:41:37 -08:00
Georgiy Kassabli
52f3471405 Fix for Yoga test failure for flexing with min stack dimension
Summary: Test fails when we have flexible child and min/max layout dimension. Yoga should flex the child to minimal size, while in reality Yoga flexes it to maximal size

Reviewed By: emilsjolander

Differential Revision: D4456312

fbshipit-source-id: 82a39bc93cf3bf2374b968e9f7403397e752908e
2017-02-06 13:00:42 -08:00
Lukas Wöhrl
e567502750 Added property display: flex and none
Summary:
Fix #241 and successor for #302

Added new property ```display``` with ```YGDisplayFlex``` and ```YGDisplayNone```. Allows to hide nodes from the layout without the need to remove it from the DOM.
Closes https://github.com/facebook/yoga/pull/369

Reviewed By: astreet

Differential Revision: D4501141

Pulled By: emilsjolander

fbshipit-source-id: 0dfeee381f6d1e4bbba81926126b83dd7abab9d6
2017-02-06 09:39:37 -08:00
Dustin Shahidehpour
c1cdc1de58 Fix warnings about icon assets.
Summary:
I incorrectly sized some assets, as a result, the sample project had some warnings about it when you built. This fixes it.
Closes https://github.com/facebook/yoga/pull/377

Differential Revision: D4515193

Pulled By: dshahidehpour

fbshipit-source-id: 3af6e79a17777bec3798bbf7294af5716f65e37a
2017-02-06 07:39:33 -08:00
Dustin Shahidehpour
f2c41f366f Made YogaKitSample build again, use cocoapods, add icon images.
Summary: The Sample app needed some love. It wouldn't build because of some import errors, adding files is very manual, and it looked bad. I have fixed all of these things.

Reviewed By: amonshiz

Differential Revision: D4508624

fbshipit-source-id: bda40defb167ef871d8d0d5bb853d8905b9682d8
2017-02-03 13:39:35 -08:00
Emil Sjolander
56d06e27cf Pass parent with down with calculateLayout to allow percentages on root node
Summary: For percentage paddings/margins/sizes to work on the root node we need to have the ability to pass down the parent sizes. This has always been possible with the C API but was never exposed to java. This diff exposes this functionality.

Reviewed By: astreet

Differential Revision: D4501016

fbshipit-source-id: 0c9502e86ff200c021c78afb7ac4b48cf11b3bdb
2017-02-03 11:24:57 -08:00
Emil Sjolander
93e327f4a5 Return raw edge style value now that we have layout outputs for them
Summary: Previously we needed to be able to return a computed value from the style edge getters to correctly handle things like RTL in frameworks such as React Native. However we now have a more correct solution with is to expose layout outputs for these edge values. This means we can go back to returning the raw value set for padding/margin/border like we do with other styles.

Reviewed By: astreet

Differential Revision: D4500892

fbshipit-source-id: e7c26bdda9ecbfc76b6cf1f384f8cf9f38284120
2017-02-03 11:24:57 -08:00
Dustin Shahidehpour
687668a4b3 Move podspec to root directory.
Summary: For our YogaKit sample project we want to add Cocoapods support and reference the local podspec. Unfortunately, this won't work unless the podspec lives in the root directory.

Reviewed By: emilsjolander

Differential Revision: D4507887

fbshipit-source-id: 919a8c8506768c90e50b3ae27deb51394db021e6
2017-02-03 10:24:55 -08:00
Emil Sjolander
cfeac79130 Fix percentage calculation when parent size is undefined
Summary: If parent size was undefined and node specified percentage size it would pass does an exact measure mode with an undefined value which broke an assertion.

Reviewed By: gkassabli

Differential Revision: D4494265

fbshipit-source-id: 9efef9e39a1b66af2d0f144575a96c919d60dbf7
2017-02-03 05:40:00 -08:00
Emil Sjolander
4227e36ca5 Add tests for wrapping to child size
Summary: Add tests for container wrapping child size

Reviewed By: gkassabli

Differential Revision: D4494263

fbshipit-source-id: bebfdd4a180b0ccd8dbb14e566613f1e64fabd7a
2017-02-03 05:40:00 -08:00
Emil Sjolander
be1c9f249e Take parent size into account when determining if style dim is defined
Summary: Ensure that a percentage size is only "defined" if the parent size is defined.

Reviewed By: gkassabli

Differential Revision: D4494258

fbshipit-source-id: 36c31444cbd113a820b067fe9e7b9560ae1d4df7
2017-02-03 05:40:00 -08:00
Lukas Wöhrl
511a129a7e Generate enums in sorted order
Summary:
This PR forces the order of the generated enums in alphabetically order. This is needed to have a predictable order of the enums across different python versions. Which reduces the pain for merging multiple enum additions.
Closes https://github.com/facebook/yoga/pull/370

Reviewed By: gkassabli

Differential Revision: D4501140

Pulled By: emilsjolander

fbshipit-source-id: 66c0ed9e4ea7a5990578b53b0a7e400c13dd53a9
2017-02-03 04:24:36 -08:00
Emil Sjolander
d62ca8c518 Use fromInt() instead of indexing values() as it allocates a new array
Summary: values() create a shallow copy of the underlying array every time as there are no immutable arrays in java. By using fromInt() we avoid this allocation.

Reviewed By: pasqualeanatriello

Differential Revision: D4494371

fbshipit-source-id: 11cff65114803e185bc67a96da0bf2a2c4a3e6d9
2017-02-02 15:39:33 -08:00
Pascal Hartig
30413265c7 Remove docs/CONTRIBUTING.md
Summary: Remove the outdated `CONTRIBUTING.md`.

Reviewed By: emilsjolander

Differential Revision: D4500973

fbshipit-source-id: 955395887330287f9973bfc21714a2c24c1fac2a
2017-02-02 05:54:39 -08:00
Pascal Hartig
bd5d8a77c9 Restore basedir format.sh behavior
Summary: Ensure that `format.sh` can be run from anywhere with the same results.

Reviewed By: emilsjolander

Differential Revision: D4494367

fbshipit-source-id: cbd2cc36476a0a54a77a732cbe1b79388f7e0c46
2017-02-01 02:39:33 -08:00
Pascal Hartig
326ae15532 Format C/C++ files
Summary: Run new `format.sh`.

Reviewed By: emilsjolander

Differential Revision: D4481501

fbshipit-source-id: 5791bee9919b44282d1549029ff8e078f253ddf8
2017-01-31 09:40:19 -08:00
Pascal Hartig
9afb65da34 Regenerate test comments
Reviewed By: emilsjolander

Differential Revision: D4482049

fbshipit-source-id: c30a6550ed175811df29c24ba03af92f3bd32713
2017-01-31 09:40:19 -08:00
Pascal Hartig
fe7643c84a Update gentest to match formatter
Reviewed By: emilsjolander

Differential Revision: D4482028

fbshipit-source-id: c6e1e0ecb0475fba62d25858c9e9960eab2701dc
2017-01-31 09:40:19 -08:00
Pascal Hartig
6daad3ae66 Update format.sh
Summary:
The format.sh was referring to an outdated `benchmarks/` directory and left out
a bunch of other C/C++ files. This updates it to cover all but the build
artifacts and vendored libraries in `lib/`.

Reviewed By: emilsjolander

Differential Revision: D4481490

fbshipit-source-id: 056e00359f794d0aa999fd65ec1ef0c657738867
2017-01-31 09:40:18 -08:00
Maël Nison
44590b8907 Updates the js build
Summary:
I've updated the js build. Let's see what Travis thinks of it!
Closes https://github.com/facebook/yoga/pull/365

Reviewed By: dshahidehpour

Differential Revision: D4488099

Pulled By: emilsjolander

fbshipit-source-id: d56ee2ccbfec84f766fcfdec9bcc9c5f610a6b0e
2017-01-31 08:39:32 -08:00
orta
4400b52aab Add support for showing the YogaKit README on CocoaPods.org
Summary:
Hey there, congrats on the launch - we use React Native at Artsy, and I've been wondering about what Yoga + Jest Snapshots for RN looks like but haven't had the time to explore that yet.

With https://github.com/CocoaPods/cocoadocs.org/pull/501 I added the ability to customize the location of the README for the front-page of the CocoaPods site. That is being deployed as I speak, so it should be available the next time you decide to ship a version of Yoga.

I also fixed the capitalisation of CocoaPods, and removed a redundant CocoaPods badge on your initial README.
Closes https://github.com/facebook/yoga/pull/366

Reviewed By: emilsjolander

Differential Revision: D4488011

Pulled By: dshahidehpour

fbshipit-source-id: 6c0c4efc23a69e1fcb936214b159b49217218b49
2017-01-31 07:39:45 -08:00
Dustin Shahidehpour
c217553cf8 Add README.md
Summary: This gives YogaKit its' own readme. #accept2ship

Reviewed By: emilsjolander

Differential Revision: D4482411

fbshipit-source-id: 24ddab586d9a12a8419ae8811fa4d03b27c1a19e
2017-01-30 11:09:45 -08:00
Emil Sjolander
6ad5003149 Align Yoga and YogaKit pod specs
Summary: Make the two podspecs more consistent with each other.

Reviewed By: dshahidehpour

Differential Revision: D4481945

fbshipit-source-id: ab782abecd709c763b4e931b6839a5cae6346281
2017-01-30 08:54:35 -08:00
Lukas Wöhrl
7c77b0e48c Fix syntax error in YGMarginTest.html
Summary:
Fixes wrongly used  ```;``` inside style declaration.
Closes https://github.com/facebook/yoga/pull/360

Reviewed By: astreet

Differential Revision: D4476067

Pulled By: emilsjolander

fbshipit-source-id: 332cdcd9a832eebc68a6d73840c1d5a10078eb66
2017-01-30 08:39:35 -08:00
Dustin Shahidehpour
7b36118df4 Add issue template.
Summary: When people file issues, they are (in-general) missing a lot of useful information. This template will now be included when people file issues. More info here: https://github.com/blog/2111-issue-and-pull-request-templates

Reviewed By: emilsjolander

Differential Revision: D4481713

fbshipit-source-id: 8c173e282438d5156d50fe40c581e18730d6a5af
2017-01-30 07:39:38 -08:00
Dustin Shahidehpour
7f0dbe5356 Add deployment target to podspec.
Summary: Without specifying the deployment target, it was default to iOS 4.3. This would cause a build error because we are `unable to synthesize weak properties` which didn't come around until iOS 5. Setting default target to iOS 8.

Reviewed By: emilsjolander

Differential Revision: D4481772

fbshipit-source-id: d3be88d0f73533c6242fc1d9045c70ad4628fd21
2017-01-30 07:39:38 -08:00
Maël Nison
b87fc217df Silents errors when running copy-sources
Summary:
Being a environment test, `npm run is-monolithic` is expected to fail when pulling the package from npm and to succeed when pulling it from github. Unfortunately, when returning false, npm will throw a tantrum by default if not explicitely disabled. It's not a hard failure, the build still complete, but it's better this way.
Closes https://github.com/facebook/yoga/pull/362

Reviewed By: gkassabli

Differential Revision: D4480608

Pulled By: emilsjolander

fbshipit-source-id: 0832a2158647f49b5230e2f658997f94774cec5b
2017-01-30 06:24:33 -08:00
Emil Sjolander
625dc4bf44 Version bump
Summary: Bump version and publish to npm + cocoapods

Reviewed By: dshahidehpour

Differential Revision: D4479027

fbshipit-source-id: 42aa81de1a5a07e3a2814670ad1cf3774519b353
2017-01-28 11:09:35 -08:00
Rui Marinho
34736a4929 Add Xamarin Android support
Summary:
Adds a Xamarin Android support for Yoga and respective tests. Closes #276 with this PR all Xamarin platforms will be covered

Need to figure a better strategy for the build names for buck with splhack .

It's failing 3 tests related with YogaNode and the GC :) classic!

![screenshot_1484353863](https://cloud.githubusercontent.com/assets/1235097/21950981/61020212-d9f8-11e6-80e1-185bd1707f9a.png)

```
Facebook.Yoga.Android.Tests.dll : 660.87 ms
 : 678.788 ms
Tests run: 130, Passed: 127, Failed: 3, Skipped: 0, Inconclusive: 0
```
Closes https://github.com/facebook/yoga/pull/340

Reviewed By: emilsjolander

Differential Revision: D4475370

Pulled By: splhack

fbshipit-source-id: f050f10415e68e9808f629b843682b0f87cca065
2017-01-27 17:54:34 -08:00
Emil Sjolander
4f37cde043 re-generate js build
Summary: npm run build:all

Reviewed By: dshahidehpour

Differential Revision: D4477027

fbshipit-source-id: 107e13134145df18a788e079be467b27d1893118
2017-01-27 14:24:40 -08:00
Guido Marucci Blas
7df60376ff CocoaPods support.
Summary:
This supersedes #309 and #305.

This is still a **work-in-progress.**

**TODO**

 - [x] Create Xcode project that builds an iOS framework
 - [x] Fix failing tests on Xcode
 - [ ] Make `pod lib lint` pass and make sure YogaKit can be included using CocoaPods
 - [ ] Add `pod lib lint` to .travis.yml
 - [x] Migrate to travis osx image with Xcode 8.2

**FOLLOW-UP**
  - [ ] Make YogaKitSample use framework built by new Xcode project.
  - [ ] Make Travis to upload prebuilt versions of the framework. More [here](https://github.com/Carthage/Carthage#use-travis-ci-to-upload-your-tagged-prebuild-frameworks)
  - [ ] Upgrade github/jekyll docs about installation using Cocoapods/Carthage
Closes https://github.com/facebook/yoga/pull/352

Reviewed By: emilsjolander

Differential Revision: D4471950

Pulled By: dshahidehpour

fbshipit-source-id: 8f30c69f9a487b26aa2e5f3b66841334b01b0ab1
2017-01-27 10:09:48 -08:00
Emil Sjolander
7fa4adb0d9 Fix aspectratio with margins
Summary: aspect ratio did not account for the widths and heights being including padding. This diff fixes that.

Reviewed By: astreet

Differential Revision: D4473024

fbshipit-source-id: 5a747e2f267b077203bb3b63e4c152847dc30774
2017-01-27 10:09:48 -08:00
Kazuki Sakamoto
abb91ae77b Remove deprecated code
Summary: - Remove classes and methods marked as `Obsolete`

Reviewed By: emilsjolander

Differential Revision: D4474945

fbshipit-source-id: 43552fa638c8b321603858a862a386c5296db2fa
2017-01-27 09:09:36 -08:00
Dustin Shahidehpour
a4b1ac83f4 Update README.md to include Pod Shield
Summary: Closes https://github.com/facebook/yoga/pull/356

Differential Revision: D4471126

Pulled By: dshahidehpour

fbshipit-source-id: 362a92225c8267cb89b12b45a98f69adf726c42d
2017-01-26 14:40:07 -08:00
Emil Sjolander
8775cdc13f Format and run codegen
Summary: run format & gentest scripts. Some of the javascript tests had not been generated recently by the looks of it.

Reviewed By: dshahidehpour

Differential Revision: D4459455

fbshipit-source-id: fc1eca58fe897c8f4a2571638b4f7035d023b479
2017-01-26 13:39:42 -08:00
Maël Nison
db732ce9fa Add YGLayoutGetBorder, counterpart of YGLayoutGetPadding
Summary:
Followup of #335, fix #326. This commit add the `YGLayoutGetBorder(node, edge)` function, which correctly takes RTL/LTR into account when resolving `EDGE_START` & `EDGE_END`.
Closes https://github.com/facebook/yoga/pull/344

Reviewed By: dshahidehpour

Differential Revision: D4459950

Pulled By: emilsjolander

fbshipit-source-id: b57eb7a5b1c181a364913c3200a3794a2b7b31a6
2017-01-26 13:39:42 -08:00
Lukas Wöhrl
7c09244c39 Fix absolute position if align-item or justify-content is center or flex-end
Summary:
Fix #310 (```center```)

additionally fixes if ```flex-end``` is set.
Closes https://github.com/facebook/yoga/pull/349

Reviewed By: dshahidehpour

Differential Revision: D4458528

Pulled By: emilsjolander

fbshipit-source-id: f073c80bfc3ea6675cb95b00283074d10e91a042
2017-01-26 13:39:41 -08:00
Dustin Shahidehpour
2cc2a5f2ff Add podspec for C-Library.
Summary: This is the first step to adding cocoapods support to YogaKit. We are going to publish a `Yoga` framework to the store that we can use as a dependency. This will also allow developers to build their own abstractions easily using the core API.

Reviewed By: nlutsenko, emilsjolander

Differential Revision: D4466788

fbshipit-source-id: 8f08bdbf524e57c88f7fc3400c4ba6ad58f98d7f
2017-01-26 10:39:36 -08:00
Lukas Wöhrl
e4b50f2a8d Fix unnecessary measure calls
Summary:
Fix #334
Closes https://github.com/facebook/yoga/pull/347

Reviewed By: dshahidehpour

Differential Revision: D4455438

Pulled By: emilsjolander

fbshipit-source-id: 013c89e71757d9048708ec85cbb6af9f33ac1ea6
2017-01-24 19:09:32 -08:00
Emil Sjolander
a2a84532ff Dont constrain absolute children to zero sized parents
Summary: Absolute children should not be constraint to the size of their parent if the parent does not have a size as this was causes the layout of the child to be skipped.

Reviewed By: gkassabli

Differential Revision: D4453612

fbshipit-source-id: e8269521560d2f42b2d6f0f0ff264a1605a57d79
2017-01-24 17:09:34 -08:00
Emil Sjolander
d391323129 Use findClassStatic instead of findClassLocal
Summary: We are saving the class reference in a static variable to should be using findClassStatic to ensure the reference is always valid.

Reviewed By: mhorowitz

Differential Revision: D4420352

fbshipit-source-id: 8c66c1b2213fe295334a9bdc4e1dd7e1a4285aae
2017-01-24 15:54:31 -08:00
David Hart
ab28ecf31b Improve test readability
Summary:
I did some stylistic changes to the Objective-C unit tests for the following reasons:

- When an equality assert fails, the error messages reads as if the value we are testing is the first argument and the value we expect is the second argument. To improve the readability of test messages, I made sure all `XCTAssertEqual` and `XCTAssertNotEqual` have the arguments in the correct order.

- Because failing equality asserts already comes with a detailed message including the value tested and the expected value, I rewrote several truth asserts on `CGSizeEqual` to two equality asserts on the width and height: when those fail, the error message are clearer.
Closes https://github.com/facebook/yoga/pull/351

Reviewed By: emilsjolander

Differential Revision: D4454484

Pulled By: dshahidehpour

fbshipit-source-id: 0c1295a4a7e8477eacfb3f4ef6648984fd102a51
2017-01-24 10:09:32 -08:00
Dustin Shahidehpour
a4bab68802 Make YogaKit tests pass whether they are run in Xcode or BUCK.
Summary: Currently, some YogaKit tests fail when they are run in Xcode, but pass in BUCK. This cleans up the tests so that they more definitively test what they say they are testing, and the results are not affected by the enviroment they are run in.

Reviewed By: emilsjolander

Differential Revision: D4453745

fbshipit-source-id: 238e41960afe63d31e9f6efdcd947cfac39f2dc4
2017-01-23 19:39:37 -08:00
Dustin Shahidehpour
e3cfacf0cb Upgrade Travis to Xcode 8.2
Summary:
Doing this externally to trigger a Travis build. This will put our Travis infra on the newest Xcode.
Closes https://github.com/facebook/yoga/pull/353

Reviewed By: emilsjolander

Differential Revision: D4453795

Pulled By: dshahidehpour

fbshipit-source-id: 23416405fdd43486c934bea0b720c217fafd7f30
2017-01-23 19:39:37 -08:00
Ahmed El-Helw
8d74e01f41 Fix typo in generated Yoga classes
Reviewed By: emilsjolander

Differential Revision: D4416273

fbshipit-source-id: fa3f87b86560121e1186cdc0ee295eb052fb3a97
2017-01-19 16:24:33 -08:00
David Hart
5404bb13d4 Fix bugs introduced with YogaKit improvements
Summary:
I'm trying to fix some bugs I introduced in my latest PR, but while writing the Unit Tests for them, I saw a really weird behaviour. The following exact piece of code WORKS inside a Yoga C++ unit test, but fails from a Objective-C unit test. I had me completely confused and blocked me in my progression. Any ideas?

```
TEST(YogaTest, stupid_test) {
  const YGNodeRef node = YGNodeNew();
  YGNodeStyleSetPosition(node, YGEdgeLeft, 1);

  ASSERT_FLOAT_EQ(1, YGNodeStyleGetPosition(node, YGEdgeLeft).value);
  ASSERT_EQ(YGUnitPixel, YGNodeStyleGetPosition(node, YGEdgeLeft).unit);

  YGNodeFree(node);
}

```

```
- (void)testPositionalPropertiesWork
{
  YGNodeRef node = YGNodeNew();
  YGNodeStyleSetPosition(node, YGEdgeLeft, 1);

  XCTAssertEqual(1, YGNodeStyleGetPosition(node, YGEdgeLeft).value);
  XCTAssertEqual(YGUnitPixel, YGNodeStyleGetPosition(node, YGEdgeLeft).unit);

  YGNodeFree(node);
}
```
Closes https://github.com/facebook/yoga/pull/328

Reviewed By: dshahidehpour

Differential Revision: D4421504

Pulled By: emilsjolander

fbshipit-source-id: f59379edf70aee87a77cd1ad2986313cdfe71b94
2017-01-18 09:24:35 -08:00
Lukas Woehrl
be8773fee0 Fix wraping calculation if min-size constraint exists
Summary:
Fixes #261
Closes https://github.com/facebook/css-layout/pull/262

Reviewed By: splhack

Differential Revision: D4245200

Pulled By: emilsjolander

fbshipit-source-id: 77d802d71010ed426511d6a01e6de1e7c9194179
2017-01-16 16:24:35 -08:00
Emil Sjolander
0bcec80dfe BREAKING - Fix sizing of container with child overflowing parent
Summary:
Fixes issue brought up in https://github.com/facebook/react-native/issues/10603

The gist of the problem is that in css it is fine for a child to overflow a parent if it feels the need to, we were not respecting this.

Reviewed By: mmmulani

Differential Revision: D4182141

fbshipit-source-id: c73fd15d2577ab846fc8a202d529d0e6e1207b75
2017-01-16 11:09:32 -08:00
Thanabodee Charoenpiriyakij
2c8c2bffda Edit README.md in Benchmarks section
Summary:
Benchmarks are not located in folder benchmark. So rename folder
and buck target from 'benchmarks' to 'benchmark'.
Closes https://github.com/facebook/yoga/pull/339

Reviewed By: gkassabli

Differential Revision: D4420355

Pulled By: emilsjolander

fbshipit-source-id: 7a1bc6ece7f4b64c7cac506357e265c1b4790a4f
2017-01-16 10:39:37 -08:00
Maël Nison
d70f289e73 Add YGLayoutGetMargin
Summary:
Fix #326. I'll open another PR once this one gets accepted to add support for `YGLayoutGetBorder` 👌
Closes https://github.com/facebook/yoga/pull/335

Reviewed By: gkassabli

Differential Revision: D4409399

Pulled By: emilsjolander

fbshipit-source-id: 8153f6701cab60b55a485f6d2e0b9f7767481090
2017-01-15 15:24:30 -08:00
Rui Marinho
498a5980e8 Add YogaKit Shared and iOS version
Summary:
Using shared code for reuse in other platforms based on iOS native implementation.

Adds YogaKit sample.

Adds YogaKit tests (same as objc).

```
YogaKitTest : 80 ms
Facebook.YogaKit.iOS.Tests.exe : 81 ms
Tests run: 11 Passed: 8 Inconclusive: 0 Failed: 3 Ignored: 1
```

Since we don't have extension properties we need to go with a extension method to get access to the YogaLayout .

I m also not sure this is leak free yet, would love some help with testing and feedback about view/node lifecycle
Closes https://github.com/facebook/yoga/pull/336

Reviewed By: splhack

Differential Revision: D4415027

Pulled By: emilsjolander

fbshipit-source-id: c88328212426c3200e6f0c48cda594cd2c432065
2017-01-15 14:54:29 -08:00
Rui Marinho
8021c5d968 Fix test bug
Summary:
Simple fix on a possible copy paste error. The test actually passes the same way by coincidence.
Closes https://github.com/facebook/yoga/pull/338

Reviewed By: dshahidehpour

Differential Revision: D4415019

Pulled By: emilsjolander

fbshipit-source-id: 823c3efc821db14b70d9dfe99ef87d1d7ebb75d0
2017-01-15 14:54:29 -08:00
Kazuki Sakamoto
c536ab214d Update buck build in Visual Studio
Summary:
- Always launch buck build for Build, but copy native library when it was changed
- Rename Facebook.Yoga.Mac.Test to Facebook.Yoga.Mac.Sample
- Add Facebook.Yoga.Mac.Tests for NUnit test.
  - "Run Unit Tests" menu item was activated for the target, but Mono still can't find libyoga.dylib
Closes https://github.com/facebook/yoga/pull/332

Reviewed By: emilsjolander

Differential Revision: D4408799

Pulled By: splhack

fbshipit-source-id: b3f5f9ebd8265cc152ca859176afbf54efa8f170
2017-01-12 10:24:54 -08:00
Dustin Shahidehpour
adb81e2a1e Update docs to show new API.
Summary: Need API needs some new docs. I also removed the repo's `.hgignore` and added everything to fbobjc `.hgignore` via `./Tools/generate_hgignore.py` which uses Yoga's `.gitignore`.

Reviewed By: emilsjolander

Differential Revision: D4403967

fbshipit-source-id: f2158e4feb27953d1d9e21c775926e6207220c4a
2017-01-12 10:24:53 -08:00
Kazuki Sakamoto
c4a3e12add Launch buck from Visual Studio (Xamarin Studio) for Mac and iOS
Summary:
Launch buck from Visual Studio before `CopyInNativeLib` in `CompileDependsOn`
- Mac `buck build //csharp:yoganet#default,shared`
- iOS `buck build //csharp:yoganet-ios`

Reviewed By: emilsjolander

Differential Revision: D4403163

fbshipit-source-id: 2e5fd3fd154ef53574129ac9cb834ae3a58f2466
2017-01-11 07:54:35 -08:00
Rui Marinho
a3d7d72421 Xamarin iOS Support
Summary:
Since there's a couple of changes after last month pr of #280 , here's a new pr for Xamarin support #276 , the idea is to add Xamarin iOS, Mac and Android support.

- Add Xamarin iOS support for Yoga, by providing a wrapper for the native lib.
- Add Xamarin iOS Unit testing project
~~- Adds a YogaKit shared implementation in c#.~~
~~- Adds a YogaKIt iOS implementation.~~
~~- Adds Yoga/YogaKit iOS sample application~~

Facebook.Yoga.iOS.Tests.exe : 169 ms
Tests run: 114 Passed: 114 Inconclusive: 0 Failed: 0 Ignored: 0

![simulator screen shot 6 jan 2017 02 05 15](https://cloud.githubusercontent.com/assets/1235097/21705017/f851e9d8-d3b4-11e6-9c44-646dab559643.png)
Closes https://github.com/facebook/yoga/pull/324

Reviewed By: emilsjolander

Differential Revision: D4401408

Pulled By: splhack

fbshipit-source-id: ecdae7967060361bef2bc25a5ef759cb9a957322
2017-01-11 07:54:35 -08:00
Emil Sjolander
47266b9ae8 Add percentage support to react native
Summary:
@public

Adds support for percentage value in react native.

syntax: property: 100 | property | '100%'

supported properties:
padding
margin
width
height
minWidth
minHeight
maxWidth
maxHeight
flexBasis

```
class Playground extends React.Component {
  render() {
    return (
      <View style={{backgroundColor: 'white', padding: 10, paddingTop: 30, height: '100%'}}>
        <Text>
          If you want to quickly test out something,
          open the Playground.js file and start coding.
        </Text>
        <View style={{backgroundColor: 'red', height: 50, width: 50}}/>
        <View style={{backgroundColor: 'blue', height: '50%', width: '50%'}}/>
      </View>
    );
  }
}
```

Reviewed By: astreet

Differential Revision: D4376549

fbshipit-source-id: c41d68a7555396f95d063a7527ee081773ac56dc
2017-01-11 04:09:34 -08:00
Emil Sjolander
e39f13a8ea Allow aspect ratio to expand beyond bounds of parent
Summary: Allow aspect ratio to expand beyond bounds of parent as is generally accepted in css

Reviewed By: passy

Differential Revision: D4397547

fbshipit-source-id: d2b1ca7b096f2f17b3efbd8f47a50678bfe7bb5f
2017-01-10 08:39:36 -08:00
Emil Sjolander
c04604dbc0 Implement java bindings for custom baseline function
Summary: Implement java bindings for custom baseline function

Differential Revision: D4392516

fbshipit-source-id: 39cf6066f8e5982268becd87e54c9ab51fbf7a90
2017-01-10 07:09:33 -08:00
Emil Sjolander
1782646723 Update aspect ratio documentation to match changes recently made
Summary: Fixes #313 https://github.com/facebook/yoga/issues/313

Reviewed By: gkassabli

Differential Revision: D4397691

fbshipit-source-id: 29daabe9a4bbde3f330e952ca5e644c7cfdbcccf
2017-01-10 06:39:41 -08:00
Kazuki Sakamoto
78e64e3d5b Add Copy Constructor for C# YogaNode
Summary:
Add Copy Constructor for convenience.

    YogaNode defaultStyle = new YogaNode
    {
      Width = 100,
      Height = 100,
    };

    YogaNode node0 = new YogaNode(defaultStyle)
    {
        FlexDirection = YogaFlexDirection.Row,
        JustifyContent = YogaJustify.FlexEnd,
    };

    YogaNode node1 = new YogaNode(defaultStyle)
    {
        AlignItems = YogaAlign.Center,
    };

Reviewed By: emilsjolander

Differential Revision: D4393234

fbshipit-source-id: b4b73071aab4dc1b3ae422969de659380bd0e3ad
2017-01-09 11:24:37 -08:00
Emil Sjolander
0acb620159 Use int instead of NSInteger for ABI compatibility
Summary:
@public

Cannot use NSInteger as NSInteger has a different size than int (which is the default type of a enum). Therefor when linking the Yoga C library into obj-c the header is a missmatch for the Yoga ABI.

Reviewed By: cwdick

Differential Revision: D4392272

fbshipit-source-id: 22b92ac8f3eb7114e81dbd9b0bec9044c3d43da5
2017-01-09 08:39:36 -08:00
David Hart
9982295e10 Improved the objective-c and swift api
Summary:
Compared to what was planned, I added the `overflow` value which seemed missing. I had to modify the implementation a bit for all values which are backed by a `YGValue`, but we should probably enable the pixel dimensions in Objective-C and Swift somehow later.
Closes https://github.com/facebook/yoga/pull/322

Reviewed By: cosmin1123

Differential Revision: D4391434

Pulled By: emilsjolander

fbshipit-source-id: e33f6f7b2bbaad29553100b7a5bb424496372110
2017-01-08 11:54:32 -08:00
Kazuki Sakamoto
8ed71b2777 Add spacing properties
Summary:
Align C# implementation with YogaKit #322
Closes https://github.com/facebook/yoga/pull/327

Reviewed By: emilsjolander

Differential Revision: D4390687

Pulled By: splhack

fbshipit-source-id: 28c87a45898fcd958a422d5e254ead0ec00d3562
2017-01-08 08:09:34 -08:00
Chris Hamons
969b3709db Add basic Xamarin.Mac support
Summary:
- Does not contain "magic" found in YogaKit yet, but enough to get started
- Simple test project showing use
- YGInteropSetLogger and YGNodeInit(IntPtr) were missing from native lib built by buck
Closes https://github.com/facebook/yoga/pull/278

Reviewed By: emilsjolander

Differential Revision: D4388480

Pulled By: splhack

fbshipit-source-id: a7387bb5b5554b6fce80d08c23e4fa18a4611cce
2017-01-08 08:09:34 -08:00
Ben Holcomb
e2a7938b26 Revert D4386906: [YogaKit] Improved the objective-c and swift api
Summary: This reverts commit 05ac0e571ef3a8ff0be31469e449a7b23f102218

Differential Revision: D4386906

fbshipit-source-id: adac0d8e71ce9f3442f3bfd14b5157f88367c998
2017-01-07 10:24:37 -08:00
Kazuki Sakamoto
70a4221b9e C# Baseline function
Summary:
same as Measure function, based on #317
Closes https://github.com/facebook/yoga/pull/321

Reviewed By: emilsjolander

Differential Revision: D4385336

Pulled By: splhack

fbshipit-source-id: b583ec79861d2e9abba31a72503e2f706bfda8e8
2017-01-07 09:09:35 -08:00
David Hart
8d320ceac2 Improved the objective-c and swift api
Summary:
Compared to what was planned, I added the `overflow` value which seemed missing. I had to modify the implementation a bit for all values which are backed by a `YGValue`, but we should probably enable the pixel dimensions in Objective-C and Swift somehow later.
Closes https://github.com/facebook/yoga/pull/322

Reviewed By: dshahidehpour

Differential Revision: D4386906

Pulled By: emilsjolander

fbshipit-source-id: 05ac0e571ef3a8ff0be31469e449a7b23f102218
2017-01-07 08:24:52 -08:00
Lukas Woehrl
c169a98be6 Baseline support
Summary:
Added baseline support (see #132)

You have the ability for a custom baseline function (```float(*YGBaselineFunc)(YGNodeRef node);```) to return whatever baseline you want.
Closes https://github.com/facebook/yoga/pull/317

Reviewed By: splhack

Differential Revision: D4385061

Pulled By: emilsjolander

fbshipit-source-id: cb8a59a09237c840fa3e21753ab68239997dab0c
2017-01-06 06:54:41 -08:00
Emil Sjolander
6d48307c8d Expose layout paddding in csharp api
Summary: Expose layout padding api from D4376572

Reviewed By: splhack

Differential Revision: D4377070

fbshipit-source-id: 501628612675e3fdce9a8e77f929cb9c6eddc209
2017-01-05 12:54:45 -08:00
Emil Sjolander
e539ecc9aa Expose layout paddding in java api
Summary: Expose layout padding api from D4376572

Reviewed By: passy

Differential Revision: D4377069

fbshipit-source-id: 2e0c04104560e1be586562b27b3457576590dc18
2017-01-05 12:54:45 -08:00
Emil Sjolander
bf5eeaf61e Add api for retrieving computed padding
Summary: Add API for retrieving the computed final padding of a node. Many frameworks such as React Native retrieve padding via `YGNodeStyleGetPadding` but given that we now support percentage values this is not correct anymore.

Differential Revision: D4376572

fbshipit-source-id: 3ffb66e77090fc1257511bec5c933f9b0c304b9f
2017-01-05 12:54:45 -08:00
Kazuki Sakamoto
a36faf89e3 Fix dll path in Unity build script
Summary: sync with vcproj

Reviewed By: emilsjolander

Differential Revision: D4384510

fbshipit-source-id: 964c5b84c063a5241b3aab0f276b2b5a080677aa
2017-01-05 12:10:03 -08:00
David Hart
29c44e281c Set nodes dirty when sizeThatFits changes
Summary:
In YogaKit, nodes are not dirtied when `sizeThatFits` of leaf nodes change. This makes it difficult to reuse views like `UILabel` when their content (text) changes. I wrote a failing test to prove it and wrote a fix by caching the latest value of `sizeThatFits` in `YGNodeBridge` and checking for changes in `YGAttachNodesFromViewHierachy` (renamed to `YGUpdateNodesFromViewHierachy` to make it clear it's not simply reattaching nodes anymore). When a new size is detected, I call `YGNodeMarkDirty` on the leaf node.

**Unfortunately**, this makes another test fail for no logical reason (`testThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond`). Either there's something I don't understand or I've un-advertedly unearthed a bug in the C implementation, but in what case would setting a node dirty make the layout return a different size?
Closes https://github.com/facebook/yoga/pull/308

Reviewed By: emilsjolander

Differential Revision: D4378826

Pulled By: dshahidehpour

fbshipit-source-id: cd0640bc863debb9e434370739416e3e33e57a08
2017-01-05 08:39:36 -08:00
David Hart
1877a97898 Fix crash when a non-leaf node becomes a leaf node
Summary:
When a non-leaf node becomes a leaf node, `YGAttachNodesFromViewHierachy` calls `YGNodeSetMeasureFunc` before `YGRemoveAllChildren`, which causes a crash because that node has children. Fixed by swapping the order of the calls and have a unit-test to make sure it works.
Closes https://github.com/facebook/yoga/pull/320

Differential Revision: D4383905

Pulled By: dshahidehpour

fbshipit-source-id: 4872b1e819f178adaaa66b1f1c233390d3ec3be9
2017-01-05 08:24:39 -08:00
Andrew Forster
bf6602ebff Update C# wrapper to support both desktop and UWP projects
Summary:
The C# wrapper project has been changed to a NETStandard (1.1) PCL allowing it
to be consumed by any project targeting .NET4.5 or greater including .NETCore
and UWP projects... The C# wrapper uses P/Invoke to call into the Native Yoga
DLL...

The "Yoga" C++ project has been updated to support ARM builds...

Added the ability to generate nuget packages for the C# wrapper that supports
copying the native DLLs to the target output directory.

Closes: https://github.com/facebook/yoga/pull/283

Reviewed By: splhack, emilsjolander

Differential Revision: D4381455

Pulled By: JoelMarcey

fbshipit-source-id: e6dc4190caa824ac63d5d5ee2eb4c7914efbb00f
2017-01-05 07:09:41 -08:00
Kazuki Sakamoto
6bcf0e3a50 Fix Unity build
Summary:
YogaValue.cs(20,30): error CS1644: Feature `expression bodied members' cannot be used because it is not part of the C# 4.0 language specification
    YogaValue.cs(21,28): error CS1644: Feature `expression bodied members' cannot be used because it is not part of the C# 4.0 language specification
Closes https://github.com/facebook/yoga/pull/316

Reviewed By: emilsjolander

Differential Revision: D4381190

Pulled By: splhack

fbshipit-source-id: fea157ac03944260d87b9f137bf966605c01a10e
2017-01-05 06:39:38 -08:00
Lukas Woehrl
d0aeabb8f0 Optimized memory alignment
Summary:
It's not much, but still 4 bytes saved here by moving the ```bool```s together. (on compilers where ```bool``` is a single byte)
Closes https://github.com/facebook/yoga/pull/319

Reviewed By: gkassabli, passy

Differential Revision: D4383686

Pulled By: emilsjolander

fbshipit-source-id: 9a48eccbb69382850c016aa6ee730526704a15f2
2017-01-05 06:24:31 -08:00
Lukas Woehrl
956df20c64 Use float instead of double for test values
Summary:
Use explicit float values to remove warning.
Closes https://github.com/facebook/yoga/pull/318

Reviewed By: gkassabli

Differential Revision: D4383687

Pulled By: emilsjolander

fbshipit-source-id: a820bf829f74a7bdaefc39e783d03b42e27d0b3b
2017-01-05 04:54:36 -08:00
Maël Nison
7108454455 Improve JS bindings
Summary:
- Fix a few things related to how npm should publish the package (sources were in the gitignore file, so I think it would have break the build during install - I fixed this by adding a npmignore that should override the gitignore rules)

- The enumerations values are now generated directly from `enums.py`

- I added percent unit support (#258) to the bindings (`.setWidthPercent` is currently exposed, but I've also added a very very little parsing to also support `.setWidth("100%")` and `.setWidth(.getWidth())`), added the missing tests, and fixed Travis.
Closes https://github.com/facebook/yoga/pull/314

Reviewed By: mikearmstrong001

Differential Revision: D4377198

Pulled By: emilsjolander

fbshipit-source-id: 774dfafd416f5421f3be59a1d181eb7056487abe
2017-01-04 04:39:40 -08:00
Dustin Shahidehpour
663a93912b Add Overflow API.
Summary: We need this for scrollviews, bring on the overflow!

Reviewed By: emilsjolander

Differential Revision: D4376759

fbshipit-source-id: a427432da5e8679dbf9fdbfe4250707e727368f4
2017-01-03 06:39:40 -08:00
Lukas Woehrl
a85bd4ad2a Add feature to use percentage as value unit
Summary:
Adds the feature to use percentage as a value unit.

You can use the function ```YGPx(float)``` and ```YGPercent(float)``` for convenience.

I did some benchmarks:

```
Without Percentage Feature - Release x86:

Stack with flex: median: 0.000000 ms, stddev: 0.146683 ms
Align stretch in undefined axis: median: 0.000000 ms, stddev: 0.136525 ms
Nested flex: median: 0.000000 ms, stddev: 0.490101 ms
Huge nested layout: median: 23.000000 ms, stddev: 0.928291 ms

Stack with flex: median: 0.000000 ms, stddev: 0.170587 ms
Align stretch in undefined axis: median: 0.000000 ms, stddev: 0.143384 ms
Nested flex: median: 0.000000 ms, stddev: 0.477791 ms
Huge nested layout: median: 22.000000 ms, stddev: 2.129779 ms

With Percentage Feature - Release x86:

Stack with flex: median: 0.000000 ms, stddev: 0.132951 ms
Align stretch in undefined axis: median: 0.000000 ms, stddev: 0.136525 ms
Nested flex: median: 0.000000 ms, stddev: 0.489570 ms
Huge nested layout: median: 21.000000 ms, stddev: 1.390476 ms
Closes https://github.com/facebook/yoga/pull/258

Reviewed By: dshahidehpour

Differential Revision: D4361945

Pulled By: emilsjolander

fbshipit-source-id: a8f5bc63ad352eb9410d792729e56664468cd76a
2017-01-02 05:24:35 -08:00
Maël Nison
6f462a72bf Adds Javascript Support
Summary:
- As mentioned in the title, this PR adds Javascript support to Yoga. Two different builds are included in this PR thanks to [nbind](https://github.com/charto/nbind), which conveniently allow to target both Node.js' native addons and browser environments via asmjs with approximately the same codebase. That should solve #215.

- All tests successfully pass on both codepaths. You can run `yarn test:all` inside the `javascript` directory to test it.

- Because of a bug in nbind, the [following PR](https://github.com/charto/nbind/pull/57) needs to be merged and a new version released before this one can be safely merged as well.

- I had to use `double` types instead of `float` in the C++ bindings because of an Emscripten [bug](https://github.com/kripken/emscripten/issues/3592) where symbols aren't correctly exported when using floats.

- There's some tweaks to do before this PR is 100% ready to merge, but I wanted to have your opinion first. What do you think of this?

 ---

To do:

- [x] Ensure th
Closes https://github.com/facebook/yoga/pull/304

Reviewed By: mikearmstrong001

Differential Revision: D4375187

Pulled By: emilsjolander

fbshipit-source-id: 47248558a9506b7c512b5ef281cd12fe1a60cab7
2017-01-02 02:24:38 -08:00
Emil Sjolander
352f592767 Allow decimal measurements on java
Summary: Preserve floating point values when passing them across the JNI bridge.

Differential Revision: D4366605

fbshipit-source-id: 0b94ee87a03a6ed918360dd9998930e780fc865d
2016-12-29 04:55:56 -08:00
Emil Sjolander
f2080e520f Move yoga docs into docs folder on master branch
Summary: Move yoga docs into master branch so that pull requests are able to include doc updates as part of other changes.

Reviewed By: JoelMarcey

Differential Revision: D4365700

fbshipit-source-id: 2f46a88974104c454c00bcdf1257abb5c4075a68
2016-12-28 04:09:48 -08:00
514 changed files with 63531 additions and 5188 deletions

View File

@@ -1,2 +1,9 @@
[cxx]
gtest_dep = //lib/gtest:gtest
[android]
target = Google Inc.:Google APIs:19
[ndk]
ndk_version = 12.1.2977051
compiler = clang
app_platform = android-19
cpu_abis = armv7, x86

17
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,17 @@
# Report
- [ ] I have searched [existing issues](https://github.com/facebook/yoga/issues) and this is not a duplicate
# Issues and Steps to Reproduce
***Replaces this with steps to repro your issue.***
# Expected Behavior
***Describe what you expected would happen.***
# Actual Behavior
***Describe what actually happened.***
# Link to Code
***If you have some code that maintainers can clone/test for themselves, bugs can be resolved much faster. Please paste a link here.***
***When applicable, use this [fiddle](https://jsfiddle.net/emilsjolander/jckmwztt/) to post a web repro.***

13
.gitignore vendored
View File

@@ -7,8 +7,18 @@
/gentest/test.html
.buckversion
# Jekyll
/.sass-cache/
/_site/
# Visual studio code
.vscode
*.pdb
*.tlog
*.obj
*.pch
*.log
*.orig
# Xcode
## Build generated
@@ -50,3 +60,6 @@ Pods/
# Carthage/Checkouts
Carthage/Build
# Gradle
.gradle

View File

@@ -1,52 +0,0 @@
.DS_STORE
/buck-cache/
/buck-out/
/.buckconfig.local
/.buckd
/gentest/test.html
.buckversion
# Visual studio code
.vscode
# Xcode
## Build generated
build/
DerivedData/
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
## Other
*.moved-aside
*.xcuserstate
## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build

1
.swift-version Normal file
View File

@@ -0,0 +1 @@
3.0

View File

@@ -6,25 +6,115 @@
# of patent rights can be found in the PATENTS file in the same directory.
os: osx
osx_image: xcode7.3
osx_image: xcode8.2
language: cpp
compiler: clang
env:
- TARGET=c
- TARGET=java
- TARGET=net
- TARGET=ios
- TARGET=js
- TARGET=android
before_install:
- brew update
- brew update > /dev/null
- brew tap facebook/fb
- brew install buck
- brew cask install java
- brew outdated xctool || brew upgrade xctool
- brew install mono
- export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
- export PATH=$JAVA_HOME/bin:$PATH
# Java
- |
if [[ $TARGET = "java" ]]; then
brew cask install java &&
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8) &&
export PATH=$JAVA_HOME/bin:$PATH
fi
# .NET
- |
if [[ $TARGET = "net" ]]; then
brew install mono
fi
# iOS
- |
if [[ $TARGET = "ios" ]]; then
brew outdated xctool || brew upgrade xctool
fi
# Emscripten (used for js tests)
# Note: cannot be ran on Linux (because it will compile Clang from its sources :|)
- |
if [[ $TARGET = "js" ]]; then
wget -O /tmp/emsdk-portable.tar.gz https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz &&
tar xf /tmp/emsdk-portable.tar.gz -C /tmp/ &&
/tmp/emsdk_portable/emsdk install latest >& /dev/null &&
/tmp/emsdk_portable/emsdk activate latest
fi
# Android
- |
if [[ $TARGET = "android" ]]; then
brew cask install java;
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8);
export PATH=$JAVA_HOME/bin:$PATH;
brew install android-sdk;
export ANDROID_SDK=/usr/local/Cellar/android-sdk/24.4.1_1;
export ANDROID_HOME=/usr/local/Cellar/android-sdk/24.4.1_1;
brew install lib32stdc++6 lib32z1;
echo y | $ANDROID_SDK/tools/android update sdk --filter android-19,addon-google_apis-google-19,build-tools-19.1.0 --no-ui;
echo y | $ANDROID_SDK/tools/android update sdk -u;
fi
# JavaScript
- |
if [[ $TARGET = "js" ]]; then (
cd javascript &&
npm install &&
unset CC && unset CXX && unset LINK &&
source /tmp/emsdk_portable/emsdk_env.sh &&
npm run build:browser
) fi
script:
- buck test //:yoga
- buck test //java:java
- buck test //YogaKit:YogaKitTests --config cxx.default_platform=iphonesimulator-x86_64 --config cxx.cflags=-DTRAVIS_CI
- sh csharp/tests/Facebook.Yoga/test_macos.sh
- buck run //benchmark:benchmark
- git checkout HEAD^
- buck run //benchmark:benchmark
# C
- |
if [[ $TARGET = "c" ]]; then
buck test --verbose 0 //:yoga &&
buck run --verbose 0 //benchmark:benchmark &&
git checkout HEAD^ &&
buck run --verbose 0 //benchmark:benchmark
fi
# Java
- |
if [[ $TARGET = "java" ]]; then
buck test --verbose 0 //java:java
fi
# .NET
- |
if [[ $TARGET = "net" ]]; then
sh csharp/tests/Facebook.Yoga/test_macos.sh
fi
# iOS
- |
if [[ $TARGET = "ios" ]]; then
buck test --verbose 0 //YogaKit:YogaKitTests --config cxx.default_platform=iphonesimulator-x86_64
fi
# Android
- |
if [[ $TARGET = "android" ]]; then
buck build --verbose 0 //android/sample:sample
fi
# JavaScript
- |
if [[ $TARGET = "js" ]]; then (
cd javascript &&
npm run test:all &&
npm run bench
) fi

54
BUCK
View File

@@ -5,38 +5,42 @@
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
include_defs('//YOGA_DEFS')
include_defs("//YOGA_DEFS")
GMOCK_OVERRIDE_FLAGS = [
# gmock does not mark mocked methods as override, ignore the warnings in tests
'-Wno-inconsistent-missing-override',
# gmock does not mark mocked methods as override, ignore the warnings in tests
"-Wno-inconsistent-missing-override",
]
COMPILER_FLAGS = BASE_COMPILER_FLAGS + ['-std=c11', '-fPIC']
TEST_COMPILER_FLAGS = BASE_COMPILER_FLAGS + GMOCK_OVERRIDE_FLAGS + ['-std=c++11']
COMPILER_FLAGS = BASE_COMPILER_FLAGS + [
"-std=c11",
"-fPIC",
]
TEST_COMPILER_FLAGS = BASE_COMPILER_FLAGS + GMOCK_OVERRIDE_FLAGS + ["-std=c++11"]
cxx_library(
name = 'yoga',
soname = 'libyogacore.$(ext)',
srcs = glob(['yoga/*.c']),
tests=[':YogaTests'],
exported_headers = subdir_glob([('', 'yoga/*.h')]),
header_namespace = '',
compiler_flags = COMPILER_FLAGS,
deps = [] if THIS_IS_FBOBJC else [
yoga_dep('lib/fb:ndklog'),
],
visibility = ['PUBLIC'],
name = "yoga",
srcs = glob(["yoga/*.c"]),
compiler_flags = COMPILER_FLAGS,
exported_headers = subdir_glob([("", "yoga/*.h")]),
header_namespace = "",
soname = "libyogacore.$(ext)",
tests = [":YogaTests"],
visibility = ["PUBLIC"],
deps = [] if THIS_IS_FBOBJC else [
yoga_dep("lib/fb:ndklog"),
],
)
cxx_test(
name = 'YogaTests',
contacts = ['emilsj@fb.com'],
srcs = glob(['tests/*.cpp']),
compiler_flags = TEST_COMPILER_FLAGS,
deps = [
':yoga',
GTEST_TARGET,
],
visibility = ['PUBLIC'],
name = "YogaTests",
srcs = glob(["tests/*.cpp"]),
compiler_flags = TEST_COMPILER_FLAGS,
contacts = ["emilsj@fb.com"],
visibility = ["PUBLIC"],
deps = [
":yoga",
GTEST_TARGET,
],
)

View File

@@ -1,4 +1,11 @@
# Yoga [![Build Status](https://travis-ci.org/facebook/yoga.svg?branch=master)](https://travis-ci.org/facebook/yoga)
# Yoga [![CocoaPods](https://img.shields.io/cocoapods/v/YogaKit.svg)](http://cocoapods.org/pods/YogaKit) [![npm](https://img.shields.io/npm/v/yoga-layout.svg)](https://www.npmjs.com/package/yoga-layout)
[![C Status](https://badges.herokuapp.com/travis/facebook/yoga?env=TARGET=c&label=C)](https://travis-ci.org/facebook/yoga)
[![Java Status](https://badges.herokuapp.com/travis/facebook/yoga?env=TARGET=java&label=Java)](https://travis-ci.org/facebook/yoga)
[![iOS Status](https://badges.herokuapp.com/travis/facebook/yoga?env=TARGET=ios&label=iOS)](https://travis-ci.org/facebook/yoga)
[![.NET Status](https://badges.herokuapp.com/travis/facebook/yoga?env=TARGET=net&label=.NET)](https://travis-ci.org/facebook/yoga)
[![JavaScript Status](https://badges.herokuapp.com/travis/facebook/yoga?env=TARGET=js&label=JavaScript)](https://travis-ci.org/facebook/yoga)
[![Android Status](https://badges.herokuapp.com/travis/facebook/yoga?env=TARGET=android&label=Android)](https://travis-ci.org/facebook/yoga)
## Building
Yoga builds with [buck](https://buckbuild.com). Make sure you install buck before contributing to Yoga. Yoga's main implementation is in C, with bindings to supported languages and frameworks. When making changes to Yoga please ensure the changes are also propagated to these bindings when applicable.
@@ -27,4 +34,4 @@ You may need to install the latest watir-webdriver gem (`gem install watir-webdr
For the main C implementation of Yoga clang-format is used to ensure a consistent code style. Please run `bash format.sh` before submitting a pull request. For other languages just try to follow the current code style.
## Benchmarks
Benchmarks are located in `benchmarks/YGBenchmark.c` and can be run with `buck run //benchmarks:benchmarks`. If you think your change has affected performance please run this before and after your change to validate that nothing has regressed. Benchmarks are run on every commit in CI.
Benchmarks are located in `benchmark/YGBenchmark.c` and can be run with `buck run //benchmark:benchmark`. If you think your change has affected performance please run this before and after your change to validate that nothing has regressed. Benchmarks are run on every commit in CI.

View File

@@ -1,5 +1,6 @@
YOGA_ROOT = '//...'
JAVA_TARGET = '//java:java'
INFER_ANNOTATIONS_TARGET = '//lib/infer-annotations:infer-annotations'
JSR_305_TARGET = '//lib/jsr-305:jsr-305'
JUNIT_TARGET = '//lib/junit:junit'
@@ -8,6 +9,13 @@ SOLOADER_TARGET = '//lib/soloader:soloader'
GTEST_TARGET = '//lib/gtest:gtest'
JNI_TARGET = '//lib/jni:jni'
FBJNI_TARGET = '//lib/fb:fbjni'
APPCOMPAT_TARGET = '//lib/appcompat:appcompat'
ANDROID_SUPPORT_TARGET = '//lib/android-support:android-support'
ANDROID_TARGET = '//android:android'
ANDROID_JAVA_TARGET = '//android/src/main/java/com/facebook/yoga/android:android'
ANDROID_RES_TARGET = '//android:res'
ANDROID_SAMPLE_JAVA_TARGET = '//android/sample/java/com/facebook/samples/yoga:yoga'
ANDROID_SAMPLE_RES_TARGET = '//android/sample:res'
THIS_IS_FBOBJC = False
@@ -28,8 +36,7 @@ BASE_COMPILER_FLAGS = [
def yoga_dep(dep):
return '//' + dep
class allow_unsafe_import:
def __enter__(self):
pass
def __exit__(self, type, value, traceback):
pass
with allow_unsafe_import():
import os.path
def isdir(filename):
return os.path.isdir(filename)

28
Yoga.podspec Normal file
View File

@@ -0,0 +1,28 @@
Pod::Spec.new do |spec|
spec.name = 'Yoga'
spec.version = '1.2.0'
spec.license = { :type => 'BSD', :file => "LICENSE" }
spec.homepage = 'https://facebook.github.io/yoga/'
spec.documentation_url = 'https://facebook.github.io/yoga/docs/api/c/'
spec.summary = 'Yoga is a cross-platform layout engine which implements Flexbox.'
spec.description = 'Yoga is a cross-platform layout engine enabling maximum collaboration within your team by implementing an API many designers are familiar with, and opening it up to developers across different platforms.'
spec.authors = 'Facebook'
spec.source = {
:git => 'https://github.com/facebook/yoga.git',
:tag => '1.2.0',
}
spec.module_name = 'yoga'
spec.requires_arc = false
spec.compiler_flags = [
'-fno-omit-frame-pointer',
'-fexceptions',
'-Wall',
'-Werror',
'-std=c11',
'-fPIC'
]
spec.source_files = 'yoga/**/*.{c,h}'
end

29
YogaKit.podspec Normal file
View File

@@ -0,0 +1,29 @@
podspec = Pod::Spec.new do |spec|
spec.name = 'YogaKit'
spec.version = '1.2.0'
spec.license = { :type => 'BSD', :file => "LICENSE" }
spec.homepage = 'https://facebook.github.io/yoga/'
spec.documentation_url = 'https://facebook.github.io/yoga/docs/api/yogakit/'
spec.summary = 'Yoga is a cross-platform layout engine which implements Flexbox.'
spec.description = 'Yoga is a cross-platform layout engine enabling maximum collaboration within your team by implementing an API many designers are familiar with, and opening it up to developers across different platforms.'
spec.authors = 'Facebook'
spec.source = {
:git => 'https://github.com/facebook/yoga.git',
:tag => '1.2.0',
}
spec.platform = :ios
spec.ios.deployment_target = '8.0'
spec.ios.frameworks = 'UIKit'
spec.dependency 'Yoga', '~> 1.2'
spec.source_files = 'YogaKit/Source/*.{h,m}'
spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h'
spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h'
end
# See https://github.com/facebook/yoga/pull/366
podspec.attributes_hash["readme"] = "YogaKit/README.md"
podspec

1
YogaKit/.swift-version Normal file
View File

@@ -0,0 +1 @@
3.0.2

View File

@@ -5,54 +5,54 @@
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
include_defs('//YOGA_DEFS')
include_defs("//YOGA_DEFS")
COMPILER_FLAGS = [
'-fobjc-arc',
'-Wconditional-uninitialized',
'-Wdangling-else',
'-Wdeprecated-declarations',
'-Wimplicit-retain-self',
'-Wincomplete-implementation',
'-Wobjc-method-access',
'-Wobjc-missing-super-calls',
'-Wmismatched-return-types',
'-Wreturn-type',
'-Wno-global-constructors',
'-Wno-shadow',
'-Wunused-const-variable',
'-Wunused-function',
'-Wunused-property-ivar',
'-Wunused-result',
'-Wunused-value',
"-fobjc-arc",
"-Wconditional-uninitialized",
"-Wdangling-else",
"-Wdeprecated-declarations",
"-Wimplicit-retain-self",
"-Wincomplete-implementation",
"-Wobjc-method-access",
"-Wobjc-missing-super-calls",
"-Wmismatched-return-types",
"-Wreturn-type",
"-Wno-global-constructors",
"-Wno-shadow",
"-Wunused-const-variable",
"-Wunused-function",
"-Wunused-property-ivar",
"-Wunused-result",
"-Wunused-value",
]
apple_library(
name = 'YogaKit',
compiler_flags = COMPILER_FLAGS,
srcs = glob(['*.m']),
exported_headers = glob(['*.h']),
frameworks = [
'$SDKROOT/System/Library/Frameworks/Foundation.framework',
'$SDKROOT/System/Library/Frameworks/UIKit.framework',
],
deps = [
yoga_dep(':yoga'),
],
visibility = ['PUBLIC'],
name = "YogaKit",
srcs = glob(["Source/**/*.m"]),
compiler_flags = COMPILER_FLAGS,
exported_headers = glob(["Source/**/*.h"]),
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
],
visibility = ["PUBLIC"],
deps = [
yoga_dep(":yoga"),
],
)
apple_test(
name = 'YogaKitTests',
compiler_flags = COMPILER_FLAGS,
info_plist = 'Tests/Info.plist',
srcs = glob(['Tests/**/*.m']),
frameworks = [
'$SDKROOT/System/Library/Frameworks/CoreGraphics.framework',
'$PLATFORM_DIR/Developer/Library/Frameworks/XCTest.framework',
],
deps = [
':YogaKit',
],
visibility = ['PUBLIC'],
name = "YogaKitTests",
srcs = glob(["Tests/**/*.m"]),
compiler_flags = COMPILER_FLAGS,
frameworks = [
"$PLATFORM_DIR/Developer/Library/Frameworks/XCTest.framework",
"$SDKROOT/System/Library/Frameworks/CoreGraphics.framework",
],
info_plist = "Tests/Info.plist",
visibility = ["PUBLIC"],
deps = [
":YogaKit",
],
)

46
YogaKit/CHANGELOG.md Normal file
View File

@@ -0,0 +1,46 @@
# CHANGELOG
The changelog for `YogaKit`.
1.2.0 (**upcoming release**)
-----
### Breaking Changes
- `applyLayout()` has now been changed to `applyLayout(preservingOrigin:)`.
- Computed properties are no longer reflected in getter's of the affected properties.
```swift
// OLD
view.yoga.margin = 10
view.yoga.marginTop // 10
view.yoga.marginLeft // 10
// NEW
view.yoga.margin = 10
view.yoga.marginTop // 0
view.yoga.marginLeft // 0
```
### Enhancements
- Pixel Rounding now uses `roundf()` instead of `round()`.
- There is now a method that allows "bulk" updates to YGLayout.
```objc
[view configureLayoutWithBlock:^(YGLayout *layout) {
layout.isEnabled = YES;
layout.width = 50;
layout.height = 50;
}];
```
```swift
view.configureLayout { (layout) in
layout.isEnabled = true
layout.width = 50
layout.height = 50
}
```
- Added new `isDirty` property, and make `markDirty` a little more performant.

22
YogaKit/README.md Normal file
View File

@@ -0,0 +1,22 @@
# YogaKit
[![CocoaPods](https://img.shields.io/cocoapods/v/YogaKit.svg?style=flat)](https://cocoapods.org/pods/YogaKit)
[![Platform](https://img.shields.io/badge/platforms-iOS-orange.svg)](https://facebook.github.io/yoga/docs/api/yogakit/)
[![Languages](https://img.shields.io/badge/languages-ObjC%20%7C%20Swift-orange.svg)](https://facebook.github.io/yoga/docs/api/yogakit/)
## Installation
YogaKit is available to install via [CocoaPods](https://cocoapods.org/).
```
pod 'YogaKit', '~> 1.1'
```
## Getting Started
Checkout the docs [here](https://facebook.github.io/yoga/docs/api/yogakit/).
We also have a sample project. To try it out, clone this repo and open `YogaKitSample.xcodeproj` in the [YogaKitSample](https://github.com/facebook/yoga/tree/master/YogaKit/YogaKitSample) directory.
## Contributing
We welcome all pull-requests! At Facebook we sync the open source version of `YogaKit` daily, so we're always testing the latest changes.
See the [CONTRIBUTING](https://github.com/facebook/yoga/blob/master/CONTRIBUTING) file for how to help out.

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "YGLayout.h"
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef void (^YGLayoutConfigurationBlock)(YGLayout *);
@interface UIView (Yoga)
/**
The YGLayout that is attached to this view. It is lazily created.
*/
@property (nonatomic, readonly, strong) YGLayout *yoga;
/**
In ObjC land, every time you access `view.yoga.*` you are adding another `objc_msgSend`
to your code. If you plan on making multiple changes to YGLayout, it's more performant
to use this method, which uses a single objc_msgSend call.
*/
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block
NS_SWIFT_NAME(configureLayout(block:));
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,36 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "UIView+Yoga.h"
#import "YGLayout+Private.h"
#import <objc/runtime.h>
static const void *kYGYogaAssociatedKey = &kYGYogaAssociatedKey;
@implementation UIView (YogaKit)
- (YGLayout *)yoga
{
YGLayout *yoga = objc_getAssociatedObject(self, kYGYogaAssociatedKey);
if (!yoga) {
yoga = [[YGLayout alloc] initWithView:self];
objc_setAssociatedObject(self, kYGYogaAssociatedKey, yoga, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return yoga;
}
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block
{
if (block != nil) {
block(self.yoga);
}
}
@end

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "YGLayout.h"
#import <yoga/Yoga.h>
@interface YGLayout ()
@property (nonatomic, assign, readonly) YGNodeRef node;
- (instancetype)initWithView:(UIView *)view;
@end

126
YogaKit/Source/YGLayout.h Normal file
View File

@@ -0,0 +1,126 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import <yoga/YGEnums.h>
@interface YGLayout : NSObject
/**
The property that decides if we should include this view when calculating layout. Defaults to YES.
*/
@property (nonatomic, readwrite, assign, setter=setIncludedInLayout:) BOOL isIncludedInLayout;
/**
The property that decides during layout/sizing whether or not styling properties should be applied.
Defaults to NO.
*/
@property (nonatomic, readwrite, assign, setter=setEnabled:) BOOL isEnabled;
@property (nonatomic, readwrite, assign) YGDirection direction;
@property (nonatomic, readwrite, assign) YGFlexDirection flexDirection;
@property (nonatomic, readwrite, assign) YGJustify justifyContent;
@property (nonatomic, readwrite, assign) YGAlign alignContent;
@property (nonatomic, readwrite, assign) YGAlign alignItems;
@property (nonatomic, readwrite, assign) YGAlign alignSelf;
@property (nonatomic, readwrite, assign) YGPositionType position;
@property (nonatomic, readwrite, assign) YGWrap flexWrap;
@property (nonatomic, readwrite, assign) YGOverflow overflow;
@property (nonatomic, readwrite, assign) YGDisplay display;
@property (nonatomic, readwrite, assign) CGFloat flexGrow;
@property (nonatomic, readwrite, assign) CGFloat flexShrink;
@property (nonatomic, readwrite, assign) CGFloat flexBasis;
@property (nonatomic, readwrite, assign) CGFloat left;
@property (nonatomic, readwrite, assign) CGFloat top;
@property (nonatomic, readwrite, assign) CGFloat right;
@property (nonatomic, readwrite, assign) CGFloat bottom;
@property (nonatomic, readwrite, assign) CGFloat start;
@property (nonatomic, readwrite, assign) CGFloat end;
@property (nonatomic, readwrite, assign) CGFloat marginLeft;
@property (nonatomic, readwrite, assign) CGFloat marginTop;
@property (nonatomic, readwrite, assign) CGFloat marginRight;
@property (nonatomic, readwrite, assign) CGFloat marginBottom;
@property (nonatomic, readwrite, assign) CGFloat marginStart;
@property (nonatomic, readwrite, assign) CGFloat marginEnd;
@property (nonatomic, readwrite, assign) CGFloat marginHorizontal;
@property (nonatomic, readwrite, assign) CGFloat marginVertical;
@property (nonatomic, readwrite, assign) CGFloat margin;
@property (nonatomic, readwrite, assign) CGFloat paddingLeft;
@property (nonatomic, readwrite, assign) CGFloat paddingTop;
@property (nonatomic, readwrite, assign) CGFloat paddingRight;
@property (nonatomic, readwrite, assign) CGFloat paddingBottom;
@property (nonatomic, readwrite, assign) CGFloat paddingStart;
@property (nonatomic, readwrite, assign) CGFloat paddingEnd;
@property (nonatomic, readwrite, assign) CGFloat paddingHorizontal;
@property (nonatomic, readwrite, assign) CGFloat paddingVertical;
@property (nonatomic, readwrite, assign) CGFloat padding;
@property (nonatomic, readwrite, assign) CGFloat borderLeftWidth;
@property (nonatomic, readwrite, assign) CGFloat borderTopWidth;
@property (nonatomic, readwrite, assign) CGFloat borderRightWidth;
@property (nonatomic, readwrite, assign) CGFloat borderBottomWidth;
@property (nonatomic, readwrite, assign) CGFloat borderStartWidth;
@property (nonatomic, readwrite, assign) CGFloat borderEndWidth;
@property (nonatomic, readwrite, assign) CGFloat borderWidth;
@property (nonatomic, readwrite, assign) CGFloat width;
@property (nonatomic, readwrite, assign) CGFloat height;
@property (nonatomic, readwrite, assign) CGFloat minWidth;
@property (nonatomic, readwrite, assign) CGFloat minHeight;
@property (nonatomic, readwrite, assign) CGFloat maxWidth;
@property (nonatomic, readwrite, assign) CGFloat maxHeight;
// Yoga specific properties, not compatible with flexbox specification
@property (nonatomic, readwrite, assign) CGFloat aspectRatio;
/**
Get the resolved direction of this node. This won't be YGDirectionInherit
*/
@property (nonatomic, readonly, assign) YGDirection resolvedDirection;
/**
Perform a layout calculation and update the frames of the views in the hierarchy with the results.
If the origin is not preserved, the root view's layout results will applied from {0,0}.
*/
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
NS_SWIFT_NAME(applyLayout(preservingOrigin:));
/**
Returns the size of the view if no constraints were given. This could equivalent to calling [self
sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
*/
@property (nonatomic, readonly, assign) CGSize intrinsicSize;
/**
Returns the number of children that are using Flexbox.
*/
@property (nonatomic, readonly, assign) NSUInteger numberOfChildren;
/**
Return a BOOL indiciating whether or not we this node contains any subviews that are included in
Yoga's layout.
*/
@property (nonatomic, readonly, assign) BOOL isLeaf;
/**
Return's a BOOL indicating if a view is dirty. When a node is dirty
it usually indicates that it will be remeasured on the next layout pass.
*/
@property (nonatomic, readonly, assign) BOOL isDirty;
/**
Mark that a view's layout needs to be recalculated. Only works for leaf views.
*/
- (void)markDirty;
@end

417
YogaKit/Source/YGLayout.m Normal file
View File

@@ -0,0 +1,417 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "YGLayout+Private.h"
#import "UIView+Yoga.h"
#define YG_PROPERTY(type, lowercased_name, capitalized_name) \
- (type)lowercased_name \
{ \
return YGNodeStyleGet##capitalized_name(self.node); \
} \
\
- (void)set##capitalized_name:(type)lowercased_name \
{ \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name); \
}
#define YG_VALUE_PROPERTY(lowercased_name, capitalized_name) \
- (CGFloat)lowercased_name \
{ \
YGValue value = YGNodeStyleGet##capitalized_name(self.node); \
if (value.unit == YGUnitPoint) { \
return value.value; \
} else { \
return YGUndefined; \
} \
} \
\
- (void)set##capitalized_name:(CGFloat)lowercased_name \
{ \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name); \
}
#define YG_EDGE_PROPERTY_GETTER(lowercased_name, capitalized_name, property, edge) \
- (CGFloat)lowercased_name \
{ \
return YGNodeStyleGet##property(self.node, edge); \
}
#define YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge) \
- (void)set##capitalized_name:(CGFloat)lowercased_name \
{ \
YGNodeStyleSet##property(self.node, edge, lowercased_name); \
}
#define YG_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_GETTER(lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
#define YG_VALUE_EDGE_PROPERTY_GETTER(objc_lowercased_name, objc_capitalized_name, c_name, edge) \
- (CGFloat)objc_lowercased_name \
{ \
YGValue value = YGNodeStyleGet##c_name(self.node, edge); \
if (value.unit == YGUnitPoint) { \
return value.value; \
} else { \
return YGUndefined; \
} \
}
#define YG_VALUE_EDGE_PROPERTY_SETTER(objc_lowercased_name, objc_capitalized_name, c_name, edge) \
- (void)set##objc_capitalized_name:(CGFloat)objc_lowercased_name \
{ \
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name); \
}
#define YG_VALUE_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
YG_VALUE_EDGE_PROPERTY_GETTER(lowercased_name, capitalized_name, property, edge) \
YG_VALUE_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
#define YG_VALUE_EDGES_PROPERTIES(lowercased_name, capitalized_name) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Left, capitalized_name##Left, capitalized_name, YGEdgeLeft) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Top, capitalized_name##Top, capitalized_name, YGEdgeTop) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Right, capitalized_name##Right, capitalized_name, YGEdgeRight) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Bottom, capitalized_name##Bottom, capitalized_name, YGEdgeBottom) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Start, capitalized_name##Start, capitalized_name, YGEdgeStart) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##End, capitalized_name##End, capitalized_name, YGEdgeEnd) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Horizontal, capitalized_name##Horizontal, capitalized_name, YGEdgeHorizontal) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Vertical, capitalized_name##Vertical, capitalized_name, YGEdgeVertical) \
YG_VALUE_EDGE_PROPERTY(lowercased_name, capitalized_name, capitalized_name, YGEdgeAll)
static YGConfigRef globalConfig;
@interface YGLayout ()
@property (nonatomic, weak, readonly) UIView *view;
@end
@implementation YGLayout
@synthesize isEnabled=_isEnabled;
@synthesize isIncludedInLayout=_isIncludedInLayout;
@synthesize node=_node;
+ (void)initialize
{
globalConfig = YGConfigNew();
YGConfigSetExperimentalFeatureEnabled(globalConfig, YGExperimentalFeatureWebFlexBasis, true);
}
- (instancetype)initWithView:(UIView*)view
{
if (self = [super init]) {
_view = view;
_node = YGNodeNewWithConfig(globalConfig);
YGNodeSetContext(_node, (__bridge void *) view);
_isEnabled = NO;
_isIncludedInLayout = YES;
}
return self;
}
- (void)dealloc
{
YGNodeFree(self.node);
}
- (BOOL)isDirty
{
return YGNodeIsDirty(self.node);
}
- (void)markDirty
{
if (self.isDirty || !self.isLeaf) {
return;
}
// Yoga is not happy if we try to mark a node as "dirty" before we have set
// the measure function. Since we already know that this is a leaf,
// this *should* be fine. Forgive me Hack Gods.
const YGNodeRef node = self.node;
if (YGNodeGetMeasureFunc(node) == NULL) {
YGNodeSetMeasureFunc(node, YGMeasureView);
}
YGNodeMarkDirty(node);
}
- (NSUInteger)numberOfChildren
{
return YGNodeGetChildCount(self.node);
}
- (BOOL)isLeaf
{
NSAssert([NSThread isMainThread], @"This method must be called on the main thread.");
if (self.isEnabled) {
for (UIView *subview in self.view.subviews) {
YGLayout *const yoga = subview.yoga;
if (yoga.isEnabled && yoga.isIncludedInLayout) {
return NO;
}
}
}
return YES;
}
#pragma mark - Style
- (YGPositionType)position
{
return YGNodeStyleGetPositionType(self.node);
}
- (void)setPosition:(YGPositionType)position
{
YGNodeStyleSetPositionType(self.node, position);
}
YG_PROPERTY(YGDirection, direction, Direction)
YG_PROPERTY(YGFlexDirection, flexDirection, FlexDirection)
YG_PROPERTY(YGJustify, justifyContent, JustifyContent)
YG_PROPERTY(YGAlign, alignContent, AlignContent)
YG_PROPERTY(YGAlign, alignItems, AlignItems)
YG_PROPERTY(YGAlign, alignSelf, AlignSelf)
YG_PROPERTY(YGWrap, flexWrap, FlexWrap)
YG_PROPERTY(YGOverflow, overflow, Overflow)
YG_PROPERTY(YGDisplay, display, Display)
YG_PROPERTY(CGFloat, flexGrow, FlexGrow)
YG_PROPERTY(CGFloat, flexShrink, FlexShrink)
YG_VALUE_PROPERTY(flexBasis, FlexBasis)
YG_VALUE_EDGE_PROPERTY(left, Left, Position, YGEdgeLeft)
YG_VALUE_EDGE_PROPERTY(top, Top, Position, YGEdgeTop)
YG_VALUE_EDGE_PROPERTY(right, Right, Position, YGEdgeRight)
YG_VALUE_EDGE_PROPERTY(bottom, Bottom, Position, YGEdgeBottom)
YG_VALUE_EDGE_PROPERTY(start, Start, Position, YGEdgeStart)
YG_VALUE_EDGE_PROPERTY(end, End, Position, YGEdgeEnd)
YG_VALUE_EDGES_PROPERTIES(margin, Margin)
YG_VALUE_EDGES_PROPERTIES(padding, Padding)
YG_EDGE_PROPERTY(borderLeftWidth, BorderLeftWidth, Border, YGEdgeLeft)
YG_EDGE_PROPERTY(borderTopWidth, BorderTopWidth, Border, YGEdgeTop)
YG_EDGE_PROPERTY(borderRightWidth, BorderRightWidth, Border, YGEdgeRight)
YG_EDGE_PROPERTY(borderBottomWidth, BorderBottomWidth, Border, YGEdgeBottom)
YG_EDGE_PROPERTY(borderStartWidth, BorderStartWidth, Border, YGEdgeStart)
YG_EDGE_PROPERTY(borderEndWidth, BorderEndWidth, Border, YGEdgeEnd)
YG_EDGE_PROPERTY(borderWidth, BorderWidth, Border, YGEdgeAll)
YG_VALUE_PROPERTY(width, Width)
YG_VALUE_PROPERTY(height, Height)
YG_VALUE_PROPERTY(minWidth, MinWidth)
YG_VALUE_PROPERTY(minHeight, MinHeight)
YG_VALUE_PROPERTY(maxWidth, MaxWidth)
YG_VALUE_PROPERTY(maxHeight, MaxHeight)
YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
#pragma mark - Layout and Sizing
- (YGDirection)resolvedDirection
{
return YGNodeLayoutGetDirection(self.node);
}
- (void)applyLayout
{
[self calculateLayoutWithSize:self.view.bounds.size];
YGApplyLayoutToViewHierarchy(self.view, NO);
}
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
{
[self calculateLayoutWithSize:self.view.bounds.size];
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
}
- (CGSize)intrinsicSize
{
const CGSize constrainedSize = {
.width = YGUndefined,
.height = YGUndefined,
};
return [self calculateLayoutWithSize:constrainedSize];
}
#pragma mark - Private
- (CGSize)calculateLayoutWithSize:(CGSize)size
{
NSAssert([NSThread isMainThread], @"Yoga calculation must be done on main.");
NSAssert(self.isEnabled, @"Yoga is not enabled for this view.");
YGAttachNodesFromViewHierachy(self.view);
const YGNodeRef node = self.node;
YGNodeCalculateLayout(
node,
size.width,
size.height,
YGNodeStyleGetDirection(node));
return (CGSize) {
.width = YGNodeLayoutGetWidth(node),
.height = YGNodeLayoutGetHeight(node),
};
}
static YGSize YGMeasureView(
YGNodeRef node,
float width,
YGMeasureMode widthMode,
float height,
YGMeasureMode heightMode)
{
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height;
UIView *view = (__bridge UIView*) YGNodeGetContext(node);
const CGSize sizeThatFits = [view sizeThatFits:(CGSize) {
.width = constrainedWidth,
.height = constrainedHeight,
}];
return (YGSize) {
.width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode),
.height = YGSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode),
};
}
static CGFloat YGSanitizeMeasurement(
CGFloat constrainedSize,
CGFloat measuredSize,
YGMeasureMode measureMode)
{
CGFloat result;
if (measureMode == YGMeasureModeExactly) {
result = constrainedSize;
} else if (measureMode == YGMeasureModeAtMost) {
result = MIN(constrainedSize, measuredSize);
} else {
result = measuredSize;
}
return result;
}
static BOOL YGNodeHasExactSameChildren(const YGNodeRef node, NSArray<UIView *> *subviews)
{
if (YGNodeGetChildCount(node) != subviews.count) {
return NO;
}
for (int i=0; i<subviews.count; i++) {
if (YGNodeGetChild(node, i) != subviews[i].yoga.node) {
return NO;
}
}
return YES;
}
static void YGAttachNodesFromViewHierachy(UIView *const view)
{
YGLayout *const yoga = view.yoga;
const YGNodeRef node = yoga.node;
// Only leaf nodes should have a measure function
if (yoga.isLeaf) {
YGRemoveAllChildren(node);
YGNodeSetMeasureFunc(node, YGMeasureView);
} else {
YGNodeSetMeasureFunc(node, NULL);
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
for (UIView *subview in view.subviews) {
if (subview.yoga.isIncludedInLayout) {
[subviewsToInclude addObject:subview];
}
}
if (!YGNodeHasExactSameChildren(node, subviewsToInclude)) {
YGRemoveAllChildren(node);
for (int i=0; i<subviewsToInclude.count; i++) {
YGNodeInsertChild(node, subviewsToInclude[i].yoga.node, i);
}
}
for (UIView *const subview in subviewsToInclude) {
YGAttachNodesFromViewHierachy(subview);
}
}
}
static void YGRemoveAllChildren(const YGNodeRef node)
{
if (node == NULL) {
return;
}
while (YGNodeGetChildCount(node) > 0) {
YGNodeRemoveChild(node, YGNodeGetChild(node, YGNodeGetChildCount(node) - 1));
}
}
static CGFloat YGRoundPixelValue(CGFloat value)
{
static CGFloat scale;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^(){
scale = [UIScreen mainScreen].scale;
});
return roundf(value * scale) / scale;
}
static void YGApplyLayoutToViewHierarchy(UIView *view, BOOL preserveOrigin)
{
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread.");
const YGLayout *yoga = view.yoga;
if (!yoga.isIncludedInLayout) {
return;
}
YGNodeRef node = yoga.node;
const CGPoint topLeft = {
YGNodeLayoutGetLeft(node),
YGNodeLayoutGetTop(node),
};
const CGPoint bottomRight = {
topLeft.x + YGNodeLayoutGetWidth(node),
topLeft.y + YGNodeLayoutGetHeight(node),
};
const CGPoint origin = preserveOrigin ? view.frame.origin : CGPointZero;
view.frame = (CGRect) {
.origin = {
.x = YGRoundPixelValue(topLeft.x + origin.x),
.y = YGRoundPixelValue(topLeft.y + origin.y),
},
.size = {
.width = YGRoundPixelValue(bottomRight.x) - YGRoundPixelValue(topLeft.x),
.height = YGRoundPixelValue(bottomRight.y) - YGRoundPixelValue(topLeft.y),
},
};
if (!yoga.isLeaf) {
for (NSUInteger i=0; i<view.subviews.count; i++) {
YGApplyLayoutToViewHierarchy(view.subviews[i], NO);
}
}
}
@end

View File

@@ -10,90 +10,190 @@
#import <XCTest/XCTest.h>
#import <YogaKit/UIView+Yoga.h>
#import <YogaKit/YGLayout+Private.h>
#import <yoga/Yoga.h>
@interface YogaKitTests : XCTestCase
@end
@implementation YogaKitTests
#ifndef TRAVIS_CI
- (void)testConfigureLayoutIsNoOpWithNilBlock
{
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
XCTAssertNoThrow([view configureLayoutWithBlock:nil]);
}
- (void)testConfigureLayoutBlockWorksWithValidBlock
{
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
[view configureLayoutWithBlock:^(YGLayout *layout){
XCTAssertNotNil(layout);
layout.isEnabled = YES;
layout.width = 25;
}];
XCTAssertTrue(view.yoga.isEnabled);
XCTAssertEqual(view.yoga.width, 25);
}
- (void)testNodesAreDeallocedWithSingleView
{
XCTAssertEqual(0, YGNodeGetInstanceCount());
__weak YGLayout *layoutRef = nil;
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
[view yg_setFlexBasis:1];
XCTAssertEqual(1, YGNodeGetInstanceCount());
view = nil;
@autoreleasepool {
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.flexBasis = 1;
XCTAssertEqual(0, YGNodeGetInstanceCount());
layoutRef = view.yoga;
XCTAssertNotNil(layoutRef);
view = nil;
}
XCTAssertNil(layoutRef);
}
- (void)testNodesAreDeallocedCascade
{
XCTAssertEqual(0, YGNodeGetInstanceCount());
__weak YGLayout *topLayout = nil;
__weak YGLayout *subviewLayout = nil;
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
[view yg_setFlexBasis:1];
@autoreleasepool {
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
topLayout = view.yoga;
topLayout.flexBasis = 1;
for (int i=0; i<10; i++) {
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
[subview yg_setFlexBasis:1];
[view addSubview:subview];
}
XCTAssertEqual(11, YGNodeGetInstanceCount());
view = nil;
subviewLayout = subview.yoga;
subviewLayout.flexBasis = 1;
XCTAssertEqual(0, YGNodeGetInstanceCount());
view = nil;
}
XCTAssertNil(topLayout);
XCTAssertNil(subviewLayout);
}
#endif
- (void)testUsesYoga
- (void)testIsEnabled
{
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
XCTAssertFalse([view yg_usesYoga]);
XCTAssertFalse(view.yoga.isEnabled);
[view yg_setUsesYoga:YES];
XCTAssertTrue([view yg_usesYoga]);
view.yoga.isEnabled = YES;
XCTAssertTrue(view.yoga.isEnabled);
[view yg_setUsesYoga:NO];
XCTAssertFalse([view yg_usesYoga]);
view.yoga.isEnabled = NO;
XCTAssertFalse(view.yoga.isEnabled);
}
- (void)testSizeThatFitsAsserts
{
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
dispatch_sync(dispatch_queue_create("com.facebook.Yoga.testing", DISPATCH_QUEUE_SERIAL), ^(void){
XCTAssertThrows([view yg_intrinsicSize]);
XCTAssertThrows(view.yoga.intrinsicSize);
});
}
- (void)testSizeThatFitsSmoke
{
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
[container yg_setUsesYoga:YES];
[container yg_setFlexDirection:YGFlexDirectionRow];
[container yg_setAlignItems:YGAlignFlexStart];
container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow;
container.yoga.alignItems = YGAlignFlexStart;
UILabel *longTextLabel = [[UILabel alloc] initWithFrame:CGRectZero];
longTextLabel.text = @"This is a very very very very very very very very long piece of text.";
longTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
longTextLabel.numberOfLines = 1;
[longTextLabel yg_setUsesYoga:YES];
[longTextLabel yg_setFlexShrink:1];
longTextLabel.yoga.isEnabled = YES;
longTextLabel.yoga.flexShrink = 1;
[container addSubview:longTextLabel];
UIView *textBadgeView = [[UIView alloc] initWithFrame:CGRectZero];
[textBadgeView yg_setUsesYoga:YES];
[textBadgeView yg_setMargin:3.0 forEdge:YGEdgeLeft];
[textBadgeView yg_setWidth:10];
[textBadgeView yg_setHeight:10];
textBadgeView.yoga.isEnabled = YES;
textBadgeView.yoga.margin = 0;
textBadgeView.yoga.width = 10;
textBadgeView.yoga.height = 10;
[container addSubview:textBadgeView];
const CGSize containerSize = [container yg_intrinsicSize];
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(514,21), containerSize), @"Size is actually %@", NSStringFromCGSize(containerSize));
const CGSize textBadgeViewSize = textBadgeView.yoga.intrinsicSize;
XCTAssertEqual(textBadgeViewSize.height, 10);
XCTAssertEqual(textBadgeViewSize.width, 10);
const CGSize containerSize = container.yoga.intrinsicSize;
const CGSize longTextLabelSize = longTextLabel.yoga.intrinsicSize;
XCTAssertEqual(longTextLabelSize.height, containerSize.height);
XCTAssertEqual(longTextLabelSize.width + textBadgeView.yoga.intrinsicSize.width, containerSize.width);
}
- (void)testPreservingOrigin
{
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,75)];
container.yoga.isEnabled = YES;
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.isEnabled = YES;
view.yoga.flexBasis = 0;
view.yoga.flexGrow = 1;
[container addSubview:view];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectZero];
view2.yoga.isEnabled = YES;
view2.yoga.marginTop = 25;
view2.yoga.flexBasis = 0;
view2.yoga.flexGrow = 1;
[container addSubview:view2];
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertEqual(50, view2.frame.origin.y);
[view2.yoga applyLayoutPreservingOrigin:NO];
XCTAssertEqual(25, view2.frame.origin.y);
}
- (void)testMarkingDirtyOnlyWorksOnLeafNodes
{
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
container.yoga.isEnabled = YES;
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
subview.yoga.isEnabled = YES;
[container addSubview:subview];
XCTAssertFalse(container.yoga.isDirty);
[container.yoga markDirty];
XCTAssertFalse(container.yoga.isDirty);
XCTAssertFalse(subview.yoga.isDirty);
[subview.yoga markDirty];
XCTAssertTrue(subview.yoga.isDirty);
}
- (void)testThatMarkingLeafsAsDirtyWillTriggerASizeRecalculation
{
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 50)];
container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow;
container.yoga.alignItems = YGAlignFlexStart;
UILabel *view = [[UILabel alloc] initWithFrame:CGRectZero];
view.text = @"This is a short text.";
view.numberOfLines = 1;
view.yoga.isEnabled = YES;
[container addSubview:view];
[container.yoga applyLayoutPreservingOrigin:YES];
CGSize const viewSizeAfterFirstPass = view.frame.size;
view.text = @"This is a slightly longer text.";
XCTAssertTrue(CGSizeEqualToSize(view.frame.size, viewSizeAfterFirstPass));
[view.yoga markDirty];
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertFalse(CGSizeEqualToSize(view.frame.size, viewSizeAfterFirstPass));
}
- (void)testFrameAndOriginPlacement
@@ -101,21 +201,28 @@
const CGSize containerSize = CGSizeMake(320, 50);
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
[container yg_setUsesYoga:YES];
[container yg_setFlexDirection:YGFlexDirectionRow];
container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow;
for (int i = 0; i < 3; i++) {
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
[subview yg_setUsesYoga:YES];
[subview yg_setFlexGrow:1];
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1;
[container addSubview:subview1];
[container addSubview:subview];
}
[container yg_applyLayout];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1;
[container addSubview:subview2];
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:0].frame, [container.subviews objectAtIndex:1].frame));
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:1].frame, [container.subviews objectAtIndex:2].frame));
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:0].frame, [container.subviews objectAtIndex:2].frame));
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1;
[container addSubview:subview3];
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertEqualWithAccuracy(subview2.frame.origin.x, CGRectGetMaxX(subview1.frame), FLT_EPSILON);
XCTAssertEqualWithAccuracy(subview3.frame.origin.x, CGRectGetMaxX(subview2.frame), FLT_EPSILON);
CGFloat totalWidth = 0;
for (UIView *view in container.subviews) {
@@ -130,33 +237,33 @@
const CGSize containerSize = CGSizeMake(300, 50);
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
[container yg_setUsesYoga:YES];
[container yg_setFlexDirection:YGFlexDirectionRow];
container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
[subview1 yg_setUsesYoga:YES];
[subview1 yg_setFlexGrow:1];
subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1;
[container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
[subview2 yg_setUsesYoga:YES];
[subview2 yg_setFlexGrow:1];
subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1;
[container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
[subview3 yg_setUsesYoga:YES];
[subview3 yg_setFlexGrow:1];
subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1;
[container addSubview:subview3];
[container yg_applyLayout];
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertTrue(CGRectEqualToRect(subview1.frame, CGRectMake(0, 0, 100, 50)));
XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50)), @"It's actually %@", NSStringFromCGRect(subview2.frame));
XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50)));
XCTAssertTrue(CGRectEqualToRect(subview3.frame, CGRectMake(200, 0, 100, 50)));
[container exchangeSubviewAtIndex:2 withSubviewAtIndex:0];
[subview2 yg_setIncludeInLayout:NO];
[container yg_applyLayout];
subview2.yoga.isIncludedInLayout = NO;
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertTrue(CGRectEqualToRect(subview3.frame, CGRectMake(0, 0, 150, 50)));
XCTAssertTrue(CGRectEqualToRect(subview1.frame, CGRectMake(150, 0, 150, 50)));
@@ -170,177 +277,383 @@
const CGSize containerSize = CGSizeMake(300, 50);
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
[container yg_setUsesYoga:YES];
[container yg_setFlexDirection:YGFlexDirectionRow];
container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
[subview1 yg_setUsesYoga:YES];
[subview1 yg_setFlexGrow:1];
subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1;
[container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
[subview2 yg_setUsesYoga:YES];
[subview2 yg_setFlexGrow:1];
subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1;
[container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
[subview3 yg_setUsesYoga:YES];
[subview3 yg_setFlexGrow:1];
subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1;
[container addSubview:subview3];
[container yg_applyLayout];
[container.yoga applyLayoutPreservingOrigin:YES];
for (UIView *view in container.subviews) {
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(view.bounds.size));
for (UIView *subview in container.subviews) {
XCTAssertEqual(subview.bounds.size.width, 100);
}
[subview3 yg_setIncludeInLayout:NO];
[container yg_applyLayout];
subview3.yoga.isIncludedInLayout = NO;
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview1.bounds.size));
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size));
XCTAssertEqual(subview1.bounds.size.width, 150);
XCTAssertEqual(subview2.bounds.size.width, 150);
// We don't set the frame to zero, so, it should be set to what it was previously at.
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview3.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview3.bounds.size));
XCTAssertEqual(subview3.bounds.size.width, 100);
}
- (void)testThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews
{
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
[container yg_setUsesYoga:YES];
[container yg_setFlexDirection:YGFlexDirectionRow];
container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
[subview1 yg_setUsesYoga:YES];
[subview1 yg_setIncludeInLayout:NO];
subview1.yoga.isEnabled = YES;
subview1.yoga.isIncludedInLayout = NO;
[container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
[subview2 yg_setUsesYoga:YES];
[subview2 yg_setIncludeInLayout:NO];
subview2.yoga.isEnabled = YES;
subview2.yoga.isIncludedInLayout = NO;
[container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
[subview3 yg_setUsesYoga:YES];
[subview3 yg_setIncludeInLayout:YES];
subview3.yoga.isEnabled = YES;
subview3.yoga.isIncludedInLayout = YES;
[container addSubview:subview3];
[container yg_applyLayout];
XCTAssertEqual(1, [container yg_numberOfChildren]);
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertEqual(container.yoga.numberOfChildren, 1);
[subview2 yg_setIncludeInLayout:YES];
[container yg_applyLayout];
XCTAssertEqual(2, [container yg_numberOfChildren]);
subview2.yoga.isIncludedInLayout = YES;
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertEqual(container.yoga.numberOfChildren, 2);
}
- (void)testThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond
{
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
[container yg_setUsesYoga:YES];
[container yg_setFlexDirection:YGFlexDirectionRow];
container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
[subview1 yg_setUsesYoga:YES];
[subview1 yg_setFlexGrow:1];
subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1;
[container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
[subview2 yg_setUsesYoga:YES];
[subview2 yg_setFlexGrow:1];
subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1;
[container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
[subview3 yg_setUsesYoga:YES];
[subview3 yg_setFlexGrow:1];
[subview3 yg_setIncludeInLayout:NO];
subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1;
subview3.yoga.isIncludedInLayout = NO;
[container addSubview:subview3];
[container yg_applyLayout];
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview1.bounds.size));
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size));
XCTAssertTrue(CGSizeEqualToSize(CGSizeZero, subview3.bounds.size), @"Actual size %@", NSStringFromCGSize(subview3.bounds.size));
XCTAssertEqual(subview1.bounds.size.width, 150);
XCTAssertEqual(subview2.bounds.size.width, 150);
XCTAssertEqual(subview3.bounds.size.width, 0);
[subview3 yg_setIncludeInLayout:YES];
[container yg_applyLayout];
for (UIView *view in container.subviews) {
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(view.bounds.size));
}
subview3.yoga.isIncludedInLayout = YES;
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertEqual(subview1.bounds.size.width, 100);
XCTAssertEqual(subview2.bounds.size.width, 100);
XCTAssertEqual(subview3.bounds.size.width, 100);
}
- (void)testyg_isLeafFlag
- (void)testIsLeafFlag
{
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
XCTAssertTrue(view.yg_isLeaf);
XCTAssertTrue(view.yoga.isLeaf);
for (int i=0; i<10; i++) {
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
[view addSubview:subview];
}
XCTAssertTrue(view.yg_isLeaf);
XCTAssertTrue(view.yoga.isLeaf);
[view yg_setUsesYoga:YES];
[view yg_setWidth:50.0];
XCTAssertTrue(view.yg_isLeaf);
view.yoga.isEnabled = YES;
view.yoga.width = 50.0;
XCTAssertTrue(view.yoga.isLeaf);
UIView *const subview = view.subviews[0];
[subview yg_setUsesYoga:YES];
[subview yg_setWidth:50.0];
XCTAssertFalse(view.yg_isLeaf);
subview.yoga.isEnabled = YES;
subview.yoga.width = 50.0;
XCTAssertFalse(view.yoga.isLeaf);
}
- (void)testThatWeCorrectlyAttachNestedViews
{
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
[container yg_setUsesYoga:YES];
[container yg_setFlexDirection:YGFlexDirectionColumn];
container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionColumn;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
[subview1 yg_setUsesYoga:YES];
[subview1 yg_setWidth:100];
[subview1 yg_setFlexGrow:1];
[subview1 yg_setFlexDirection:YGFlexDirectionColumn];
subview1.yoga.isEnabled = YES;
subview1.yoga.width = 100;
subview1.yoga.flexGrow = 1;
subview1.yoga.flexDirection = YGFlexDirectionColumn;
[container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
[subview2 yg_setUsesYoga:YES];
[subview2 yg_setWidth:150];
[subview2 yg_setFlexGrow:1];
[subview2 yg_setFlexDirection:YGFlexDirectionColumn];
subview2.yoga.isEnabled = YES;
subview2.yoga.width = 150;
subview2.yoga.flexGrow = 1;
subview2.yoga.flexDirection = YGFlexDirectionColumn;
[container addSubview:subview2];
for (UIView *view in @[subview1, subview2]) {
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero];
[someView yg_setUsesYoga:YES];
[someView yg_setFlexGrow:1];
someView.yoga.isEnabled = YES;
someView.yoga.flexGrow = 1;
[view addSubview:someView];
}
[container yg_applyLayout];
[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 yg_setUsesYoga:YES];
[someView yg_setFlexGrow:1];
someView.yoga.isEnabled = YES;
someView.yoga.flexGrow = 1;
[view addSubview:someView];
}
[container yg_applyLayout];
[container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 25), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview1.bounds.size));
XCTAssertEqual(subview1.bounds.size.width, 100);
XCTAssertEqual(subview1.bounds.size.height, 25);
for (UIView *subview in subview1.subviews) {
const CGSize subviewSize = subview.bounds.size;
XCTAssertFalse(CGSizeEqualToSize(CGSizeZero, subviewSize));
XCTAssertNotEqual(subviewSize.width, 0);
XCTAssertNotEqual(subviewSize.height, 0);
XCTAssertFalse(isnan(subviewSize.height));
XCTAssertFalse(isnan(subviewSize.width));
}
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 25), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size));
XCTAssertEqual(subview2.bounds.size.width, 150);
XCTAssertEqual(subview2.bounds.size.height, 25);
for (UIView *subview in subview2.subviews) {
const CGSize subviewSize = subview.bounds.size;
XCTAssertFalse(CGSizeEqualToSize(CGSizeZero, subview.bounds.size));
XCTAssertNotEqual(subviewSize.width, 0);
XCTAssertNotEqual(subviewSize.height, 0);
XCTAssertFalse(isnan(subviewSize.height));
XCTAssertFalse(isnan(subviewSize.width));
}
}
- (void)testThatANonLeafNodeCanBecomeALeafNode
{
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
container.yoga.isEnabled = YES;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES;
[container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES;
[subview1 addSubview:subview2];
[container.yoga applyLayoutPreservingOrigin:YES];
[subview2 removeFromSuperview];
[container.yoga applyLayoutPreservingOrigin:YES];
}
- (void)testPositionalPropertiesWork
{
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.left = 1;
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeLeft).value, 1);
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeLeft).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.left, 1);
view.yoga.right = 2;
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeRight).value, 2);
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeRight).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.right, 2);
view.yoga.top = 3;
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeTop).value, 3);
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeTop).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.top, 3);
view.yoga.bottom = 4;
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeBottom).value, 4);
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeBottom).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.bottom, 4);
view.yoga.start = 5;
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeStart).value, 5);
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeStart).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.start, 5);
view.yoga.end = 6;
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeEnd).value, 6);
XCTAssertEqual(YGNodeStyleGetPosition(view.yoga.node, YGEdgeEnd).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.end, 6);
}
- (void)testMarginPropertiesWork
{
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.margin = 1;
XCTAssertEqual(view.yoga.margin, 1);
XCTAssertTrue(isnan(view.yoga.marginLeft));
XCTAssertTrue(isnan(view.yoga.marginRight));
XCTAssertTrue(isnan(view.yoga.marginStart));
XCTAssertTrue(isnan(view.yoga.marginEnd));
XCTAssertTrue(isnan(view.yoga.marginTop));
XCTAssertTrue(isnan(view.yoga.marginBottom));
XCTAssertTrue(isnan(view.yoga.marginHorizontal));
XCTAssertTrue(isnan(view.yoga.marginVertical));
view.yoga.marginHorizontal = 2;
XCTAssertEqual(view.yoga.marginHorizontal, 2);
XCTAssertTrue(isnan(view.yoga.marginLeft));
XCTAssertTrue(isnan(view.yoga.marginRight));
XCTAssertTrue(isnan(view.yoga.marginStart));
XCTAssertTrue(isnan(view.yoga.marginEnd));
view.yoga.marginVertical = 3;
XCTAssertEqual(view.yoga.marginVertical, 3);
XCTAssertTrue(isnan(view.yoga.marginTop));
XCTAssertTrue(isnan(view.yoga.marginBottom));
view.yoga.marginLeft = 4;
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeLeft).value, 4);
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeLeft).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.marginLeft, 4);
view.yoga.marginRight = 5;
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeRight).value, 5);
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeRight).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.marginRight, 5);
view.yoga.marginTop = 6;
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeTop).value, 6);
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeTop).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.marginTop, 6);
view.yoga.marginBottom = 7;
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeBottom).value, 7);
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeBottom).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.marginBottom, 7);
view.yoga.marginStart = 8;
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeStart).value, 8);
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeStart).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.marginStart, 8);
view.yoga.marginEnd = 9;
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeEnd).value, 9);
XCTAssertEqual(YGNodeStyleGetMargin(view.yoga.node, YGEdgeEnd).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.marginEnd, 9);
}
- (void)testPaddingPropertiesWork
{
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.padding = 1;
XCTAssertEqual(view.yoga.padding, 1);
XCTAssertTrue(isnan(view.yoga.paddingLeft));
XCTAssertTrue(isnan(view.yoga.paddingRight));
XCTAssertTrue(isnan(view.yoga.paddingStart));
XCTAssertTrue(isnan(view.yoga.paddingEnd));
XCTAssertTrue(isnan(view.yoga.paddingTop));
XCTAssertTrue(isnan(view.yoga.paddingBottom));
XCTAssertTrue(isnan(view.yoga.paddingHorizontal));
XCTAssertTrue(isnan(view.yoga.paddingVertical));
view.yoga.paddingHorizontal = 2;
XCTAssertEqual(view.yoga.paddingHorizontal, 2);
XCTAssertTrue(isnan(view.yoga.paddingLeft));
XCTAssertTrue(isnan(view.yoga.paddingRight));
XCTAssertTrue(isnan(view.yoga.paddingStart));
XCTAssertTrue(isnan(view.yoga.paddingEnd));
view.yoga.paddingVertical = 3;
XCTAssertEqual(view.yoga.paddingVertical, 3);
XCTAssertTrue(isnan(view.yoga.paddingTop));
XCTAssertTrue(isnan(view.yoga.paddingBottom));
view.yoga.paddingLeft = 4;
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeLeft).value, 4);
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeLeft).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.paddingLeft, 4);
view.yoga.paddingRight = 5;
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeRight).value, 5);
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeRight).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.paddingRight, 5);
view.yoga.paddingTop = 6;
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeTop).value, 6);
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeTop).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.paddingTop, 6);
view.yoga.paddingBottom = 7;
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeBottom).value, 7);
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeBottom).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.paddingBottom, 7);
view.yoga.paddingStart = 8;
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeStart).value, 8);
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeStart).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.paddingStart, 8);
view.yoga.paddingEnd = 9;
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeEnd).value, 9);
XCTAssertEqual(YGNodeStyleGetPadding(view.yoga.node, YGEdgeEnd).unit, YGUnitPoint);
XCTAssertEqual(view.yoga.paddingEnd, 9);
}
- (void)testBorderWidthPropertiesWork
{
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.borderWidth = 1;
XCTAssertEqual(view.yoga.borderWidth, 1);
XCTAssertTrue(isnan(view.yoga.borderLeftWidth));
XCTAssertTrue(isnan(view.yoga.borderRightWidth));
XCTAssertTrue(isnan(view.yoga.borderStartWidth));
XCTAssertTrue(isnan(view.yoga.borderEndWidth));
XCTAssertTrue(isnan(view.yoga.borderTopWidth));
XCTAssertTrue(isnan(view.yoga.borderBottomWidth));
view.yoga.borderLeftWidth = 2;
XCTAssertEqual(view.yoga.borderLeftWidth, 2);
view.yoga.borderRightWidth = 3;
XCTAssertEqual(view.yoga.borderRightWidth, 3);
view.yoga.borderTopWidth = 4;
XCTAssertEqual(view.yoga.borderTopWidth, 4);
view.yoga.borderBottomWidth = 5;
XCTAssertEqual(view.yoga.borderBottomWidth, 5);
view.yoga.borderStartWidth = 6;
XCTAssertEqual(view.yoga.borderStartWidth, 6);
view.yoga.borderEndWidth = 7;
XCTAssertEqual(view.yoga.borderEndWidth, 7);
}
@end

View File

@@ -1,77 +0,0 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import <yoga/Yoga.h>
@interface UIView (Yoga)
/**
The property that decides if we should include this view when calculating layout. Defaults to YES.
*/
@property (nonatomic, readwrite, assign, setter=yg_setIncludeInLayout:) BOOL yg_includeInLayout;
/**
The property that decides during layout/sizing whether or not yg_* properties should be applied. Defaults to NO.
*/
@property (nonatomic, readwrite, assign, setter=yg_setUsesYoga:) BOOL yg_usesYoga;
- (void)yg_setDirection:(YGDirection)direction;
- (void)yg_setFlexDirection:(YGFlexDirection)flexDirection;
- (void)yg_setJustifyContent:(YGJustify)justifyContent;
- (void)yg_setAlignContent:(YGAlign)alignContent;
- (void)yg_setAlignItems:(YGAlign)alignItems;
- (void)yg_setAlignSelf:(YGAlign)alignSelf;
- (void)yg_setPositionType:(YGPositionType)positionType;
- (void)yg_setFlexWrap:(YGWrap)flexWrap;
- (void)yg_setFlexGrow:(CGFloat)flexGrow;
- (void)yg_setFlexShrink:(CGFloat)flexShrink;
- (void)yg_setFlexBasis:(CGFloat)flexBasis;
- (void)yg_setPosition:(CGFloat)position forEdge:(YGEdge)edge;
- (void)yg_setMargin:(CGFloat)margin forEdge:(YGEdge)edge;
- (void)yg_setPadding:(CGFloat)padding forEdge:(YGEdge)edge;
- (void)yg_setWidth:(CGFloat)width;
- (void)yg_setHeight:(CGFloat)height;
- (void)yg_setMinWidth:(CGFloat)minWidth;
- (void)yg_setMinHeight:(CGFloat)minHeight;
- (void)yg_setMaxWidth:(CGFloat)maxWidth;
- (void)yg_setMaxHeight:(CGFloat)maxHeight;
// Yoga specific properties, not compatible with flexbox specification
- (void)yg_setAspectRatio:(CGFloat)aspectRatio;
/**
Get the resolved direction of this node. This won't be YGDirectionInherit
*/
- (YGDirection)yg_resolvedDirection;
/**
Perform a layout calculation and update the frames of the views in the hierarchy with the results
*/
- (void)yg_applyLayout;
/**
Returns the size of the view if no constraints were given. This could equivalent to calling [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
*/
- (CGSize)yg_intrinsicSize;
/**
Returns the number of children that are using Flexbox.
*/
- (NSUInteger)yg_numberOfChildren;
/**
Return a BOOL indiciating whether or not we this node contains any subviews that are included in Yoga's layout.
*/
- (BOOL)yg_isLeaf;
@end

View File

@@ -1,397 +0,0 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "UIView+Yoga.h"
#import <objc/runtime.h>
@interface YGNodeBridge : NSObject
@property (nonatomic, assign, readonly) YGNodeRef cnode;
@end
@implementation YGNodeBridge
+ (void)initialize
{
YGSetExperimentalFeatureEnabled(YGExperimentalFeatureWebFlexBasis, true);
}
- (instancetype)init
{
if ([super init]) {
_cnode = YGNodeNew();
}
return self;
}
- (void)dealloc
{
YGNodeFree(_cnode);
}
@end
@implementation UIView (Yoga)
- (BOOL)yg_usesYoga
{
NSNumber *usesYoga = objc_getAssociatedObject(self, @selector(yg_usesYoga));
return [usesYoga boolValue];
}
- (BOOL)yg_includeInLayout
{
NSNumber *includeInLayout = objc_getAssociatedObject(self, @selector(yg_includeInLayout));
return (includeInLayout != nil) ? [includeInLayout boolValue] : YES;
}
- (NSUInteger)yg_numberOfChildren
{
return YGNodeGetChildCount([self ygNode]);
}
- (BOOL)yg_isLeaf
{
NSAssert([NSThread isMainThread], @"This method must be called on the main thread.");
if ([self yg_usesYoga]) {
for (UIView *subview in self.subviews) {
if ([subview yg_usesYoga] && [subview yg_includeInLayout]) {
return NO;
}
}
}
return YES;
}
#pragma mark - Setters
- (void)yg_setIncludeInLayout:(BOOL)includeInLayout
{
objc_setAssociatedObject(
self,
@selector(yg_includeInLayout),
@(includeInLayout),
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)yg_setUsesYoga:(BOOL)enabled
{
objc_setAssociatedObject(
self,
@selector(yg_usesYoga),
@(enabled),
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)yg_setDirection:(YGDirection)direction
{
YGNodeStyleSetDirection([self ygNode], direction);
}
- (void)yg_setFlexDirection:(YGFlexDirection)flexDirection
{
YGNodeStyleSetFlexDirection([self ygNode], flexDirection);
}
- (void)yg_setJustifyContent:(YGJustify)justifyContent
{
YGNodeStyleSetJustifyContent([self ygNode], justifyContent);
}
- (void)yg_setAlignContent:(YGAlign)alignContent
{
YGNodeStyleSetAlignContent([self ygNode], alignContent);
}
- (void)yg_setAlignItems:(YGAlign)alignItems
{
YGNodeStyleSetAlignItems([self ygNode], alignItems);
}
- (void)yg_setAlignSelf:(YGAlign)alignSelf
{
YGNodeStyleSetAlignSelf([self ygNode], alignSelf);
}
- (void)yg_setPositionType:(YGPositionType)positionType
{
YGNodeStyleSetPositionType([self ygNode], positionType);
}
- (void)yg_setFlexWrap:(YGWrap)flexWrap
{
YGNodeStyleSetFlexWrap([self ygNode], flexWrap);
}
- (void)yg_setFlexGrow:(CGFloat)flexGrow
{
YGNodeStyleSetFlexGrow([self ygNode], flexGrow);
}
- (void)yg_setFlexShrink:(CGFloat)flexShrink
{
YGNodeStyleSetFlexShrink([self ygNode], flexShrink);
}
- (void)yg_setFlexBasis:(CGFloat)flexBasis
{
YGNodeStyleSetFlexBasis([self ygNode], flexBasis);
}
- (void)yg_setPosition:(CGFloat)position forEdge:(YGEdge)edge
{
YGNodeStyleSetPosition([self ygNode], edge, position);
}
- (void)yg_setMargin:(CGFloat)margin forEdge:(YGEdge)edge
{
YGNodeStyleSetMargin([self ygNode], edge, margin);
}
- (void)yg_setPadding:(CGFloat)padding forEdge:(YGEdge)edge
{
YGNodeStyleSetPadding([self ygNode], edge, padding);
}
- (void)yg_setWidth:(CGFloat)width
{
YGNodeStyleSetWidth([self ygNode], width);
}
- (void)yg_setHeight:(CGFloat)height
{
YGNodeStyleSetHeight([self ygNode], height);
}
- (void)yg_setMinWidth:(CGFloat)minWidth
{
YGNodeStyleSetMinWidth([self ygNode], minWidth);
}
- (void)yg_setMinHeight:(CGFloat)minHeight
{
YGNodeStyleSetMinHeight([self ygNode], minHeight);
}
- (void)yg_setMaxWidth:(CGFloat)maxWidth
{
YGNodeStyleSetMaxWidth([self ygNode], maxWidth);
}
- (void)yg_setMaxHeight:(CGFloat)maxHeight
{
YGNodeStyleSetMaxHeight([self ygNode], maxHeight);
}
- (void)yg_setAspectRatio:(CGFloat)aspectRatio
{
YGNodeStyleSetAspectRatio([self ygNode], aspectRatio);
}
#pragma mark - Layout and Sizing
- (YGDirection)yg_resolvedDirection
{
return YGNodeLayoutGetDirection([self ygNode]);
}
- (void)yg_applyLayout
{
[self calculateLayoutWithSize:self.bounds.size];
YGApplyLayoutToViewHierarchy(self);
}
- (CGSize)yg_intrinsicSize
{
const CGSize constrainedSize = {
.width = YGUndefined,
.height = YGUndefined,
};
return [self calculateLayoutWithSize:constrainedSize];
}
#pragma mark - Private
- (YGNodeRef)ygNode
{
YGNodeBridge *node = objc_getAssociatedObject(self, @selector(ygNode));
if (!node) {
node = [YGNodeBridge new];
YGNodeSetContext(node.cnode, (__bridge void *) self);
objc_setAssociatedObject(self, @selector(ygNode), node, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return node.cnode;
}
- (CGSize)calculateLayoutWithSize:(CGSize)size
{
NSAssert([NSThread isMainThread], @"YG Layout calculation must be done on main.");
NSAssert([self yg_usesYoga], @"YG Layout is not enabled for this view.");
YGAttachNodesFromViewHierachy(self);
const YGNodeRef node = [self ygNode];
YGNodeCalculateLayout(
node,
size.width,
size.height,
YGNodeStyleGetDirection(node));
return (CGSize) {
.width = YGNodeLayoutGetWidth(node),
.height = YGNodeLayoutGetHeight(node),
};
}
static YGSize YGMeasureView(
YGNodeRef node,
float width,
YGMeasureMode widthMode,
float height,
YGMeasureMode heightMode)
{
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height;
UIView *view = (__bridge UIView*) YGNodeGetContext(node);
const CGSize sizeThatFits = [view sizeThatFits:(CGSize) {
.width = constrainedWidth,
.height = constrainedHeight,
}];
return (YGSize) {
.width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode),
.height = YGSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode),
};
}
static CGFloat YGSanitizeMeasurement(
CGFloat constrainedSize,
CGFloat measuredSize,
YGMeasureMode measureMode)
{
CGFloat result;
if (measureMode == YGMeasureModeExactly) {
result = constrainedSize;
} else if (measureMode == YGMeasureModeAtMost) {
result = MIN(constrainedSize, measuredSize);
} else {
result = measuredSize;
}
return result;
}
static 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].ygNode) {
return NO;
}
}
return YES;
}
static void YGAttachNodesFromViewHierachy(UIView *const view)
{
const YGNodeRef node = [view ygNode];
// Only leaf nodes should have a measure function
if (view.yg_isLeaf) {
YGNodeSetMeasureFunc(node, YGMeasureView);
YGRemoveAllChildren(node);
} else {
YGNodeSetMeasureFunc(node, NULL);
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
for (UIView *subview in view.subviews) {
if ([subview yg_includeInLayout]) {
[subviewsToInclude addObject:subview];
}
}
if (!YGNodeHasExactSameChildren(node, subviewsToInclude)) {
YGRemoveAllChildren(node);
for (int i=0; i<subviewsToInclude.count; i++) {
YGNodeInsertChild(node, [subviewsToInclude[i] ygNode], i);
}
}
for (UIView *const subview in subviewsToInclude) {
YGAttachNodesFromViewHierachy(subview);
}
}
}
static void YGRemoveAllChildren(const YGNodeRef node)
{
if (node == NULL) {
return;
}
while (YGNodeGetChildCount(node) > 0) {
YGNodeRemoveChild(node, YGNodeGetChild(node, YGNodeGetChildCount(node) - 1));
}
}
static CGFloat YGRoundPixelValue(CGFloat value)
{
static CGFloat scale;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^(){
scale = [UIScreen mainScreen].scale;
});
return round(value * scale) / scale;
}
static void YGApplyLayoutToViewHierarchy(UIView *view)
{
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread.");
if (![view yg_includeInLayout]) {
return;
}
YGNodeRef node = [view ygNode];
const CGPoint topLeft = {
YGNodeLayoutGetLeft(node),
YGNodeLayoutGetTop(node),
};
const CGPoint bottomRight = {
topLeft.x + YGNodeLayoutGetWidth(node),
topLeft.y + YGNodeLayoutGetHeight(node),
};
view.frame = (CGRect) {
.origin = {
.x = YGRoundPixelValue(topLeft.x),
.y = YGRoundPixelValue(topLeft.y),
},
.size = {
.width = YGRoundPixelValue(bottomRight.x) - YGRoundPixelValue(topLeft.x),
.height = YGRoundPixelValue(bottomRight.y) - YGRoundPixelValue(topLeft.y),
},
};
if (!view.yg_isLeaf) {
for (NSUInteger i=0; i<view.subviews.count; i++) {
YGApplyLayoutToViewHierarchy(view.subviews[i]);
}
}
}
@end

View File

@@ -0,0 +1,6 @@
use_frameworks!
target 'YogaKitSample' do
pod 'YogaKit', :path => '../../YogaKit.podspec'
pod 'IGListKit', '~> 2.1.0'
end

View 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.2.0)
- YogaKit (1.2.0):
- Yoga (~> 1.2)
DEPENDENCIES:
- IGListKit (~> 2.1.0)
- YogaKit (from `../../YogaKit.podspec`)
EXTERNAL SOURCES:
YogaKit:
:path: "../../YogaKit.podspec"
SPEC CHECKSUMS:
IGListKit: b826c68ef7a4ae1626c09d4d3e1ea7a169e6c36e
Yoga: 20fc010c282cc5f3c27ce512de1329cd1e72b077
YogaKit: 72d5c8a806dc5cf2aa50c93a6dd88913cdbec6fe
PODFILE CHECKSUM: 216f8e7127767709e0e43f3711208d238fa5c404
COCOAPODS: 1.2.0

View File

@@ -7,21 +7,27 @@
objects = {
/* Begin PBXBuildFile section */
13687D481DF8748400E7C260 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13687D471DF8748400E7C260 /* main.m */; };
13687D4B1DF8748400E7C260 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13687D4A1DF8748400E7C260 /* AppDelegate.m */; };
13687D4E1DF8748400E7C260 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13687D4D1DF8748400E7C260 /* ViewController.m */; };
13687D531DF8748400E7C260 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13687D521DF8748400E7C260 /* Assets.xcassets */; };
13687D781DF878C600E7C260 /* YGEnums.h in yoga */ = {isa = PBXBuildFile; fileRef = 13687D5E1DF8778F00E7C260 /* YGEnums.h */; };
13687D791DF878C600E7C260 /* YGMacros.h in yoga */ = {isa = PBXBuildFile; fileRef = 13687D5F1DF8778F00E7C260 /* YGMacros.h */; };
13687D7A1DF878C600E7C260 /* Yoga.h in yoga */ = {isa = PBXBuildFile; fileRef = 13687D631DF8778F00E7C260 /* Yoga.h */; };
13687D7C1DF878DD00E7C260 /* UIView+Yoga.h in YogaKit */ = {isa = PBXBuildFile; fileRef = 13687D691DF8778F00E7C260 /* UIView+Yoga.h */; };
13687D801DF87CEC00E7C260 /* UIView+Yoga.m in Sources */ = {isa = PBXBuildFile; fileRef = 13687D6A1DF8778F00E7C260 /* UIView+Yoga.m */; };
13687D811DF87CF200E7C260 /* YGNodeList.c in Sources */ = {isa = PBXBuildFile; fileRef = 13687D601DF8778F00E7C260 /* YGNodeList.c */; };
13687D821DF87CF200E7C260 /* Yoga.c in Sources */ = {isa = PBXBuildFile; fileRef = 13687D621DF8778F00E7C260 /* Yoga.c */; };
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;
@@ -29,9 +35,6 @@
dstPath = include/yoga;
dstSubfolderSpec = 16;
files = (
13687D781DF878C600E7C260 /* YGEnums.h in yoga */,
13687D791DF878C600E7C260 /* YGMacros.h in yoga */,
13687D7A1DF878C600E7C260 /* Yoga.h in yoga */,
);
name = yoga;
runOnlyForDeploymentPostprocessing = 0;
@@ -42,7 +45,6 @@
dstPath = include/YogaKit;
dstSubfolderSpec = 16;
files = (
13687D7C1DF878DD00E7C260 /* UIView+Yoga.h in YogaKit */,
);
name = YogaKit;
runOnlyForDeploymentPostprocessing = 0;
@@ -51,23 +53,19 @@
/* Begin PBXFileReference section */
13687D431DF8748400E7C260 /* YogaKitSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YogaKitSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
13687D471DF8748400E7C260 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
13687D491DF8748400E7C260 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
13687D4A1DF8748400E7C260 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
13687D4C1DF8748400E7C260 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
13687D4D1DF8748400E7C260 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
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>"; };
13687D5E1DF8778F00E7C260 /* YGEnums.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGEnums.h; sourceTree = "<group>"; };
13687D5F1DF8778F00E7C260 /* YGMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGMacros.h; sourceTree = "<group>"; };
13687D601DF8778F00E7C260 /* YGNodeList.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = YGNodeList.c; sourceTree = "<group>"; };
13687D611DF8778F00E7C260 /* YGNodeList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGNodeList.h; sourceTree = "<group>"; };
13687D621DF8778F00E7C260 /* Yoga.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Yoga.c; sourceTree = "<group>"; };
13687D631DF8778F00E7C260 /* Yoga.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Yoga.h; sourceTree = "<group>"; };
13687D691DF8778F00E7C260 /* UIView+Yoga.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+Yoga.h"; sourceTree = "<group>"; };
13687D6A1DF8778F00E7C260 /* UIView+Yoga.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+Yoga.m"; 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 */
@@ -77,6 +75,14 @@
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;
};
@@ -86,11 +92,10 @@
13687D3A1DF8748300E7C260 = {
isa = PBXGroup;
children = (
13687D5D1DF8778F00E7C260 /* yoga */,
13687D641DF8778F00E7C260 /* YogaKit */,
13687D451DF8748400E7C260 /* YogaKitSample */,
13687D441DF8748400E7C260 /* Products */,
13687D831DF87D1E00E7C260 /* Frameworks */,
E1C759E3C8E84821213ECE8D /* Pods */,
);
sourceTree = "<group>";
};
@@ -98,6 +103,7 @@
isa = PBXGroup;
children = (
13687D431DF8748400E7C260 /* YogaKitSample.app */,
638A944F1E215CC800A726AD /* YogaKitSampleTests.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -105,58 +111,52 @@
13687D451DF8748400E7C260 /* YogaKitSample */ = {
isa = PBXGroup;
children = (
13687D491DF8748400E7C260 /* AppDelegate.h */,
13687D4A1DF8748400E7C260 /* AppDelegate.m */,
13687D4C1DF8748400E7C260 /* ViewController.h */,
13687D4D1DF8748400E7C260 /* ViewController.m */,
40BD9F4E1E47902F002790A9 /* Views */,
40BD9F481E4784B3002790A9 /* ViewControllers */,
638A94471E1F06D100A726AD /* ExamplesViewController.swift */,
13687D521DF8748400E7C260 /* Assets.xcassets */,
13687D571DF8748400E7C260 /* Info.plist */,
13687D461DF8748400E7C260 /* Supporting Files */,
40BD9F451E477A09002790A9 /* AppDelegate.swift */,
);
path = YogaKitSample;
sourceTree = "<group>";
};
13687D461DF8748400E7C260 /* Supporting Files */ = {
isa = PBXGroup;
children = (
13687D471DF8748400E7C260 /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
13687D5D1DF8778F00E7C260 /* yoga */ = {
isa = PBXGroup;
children = (
13687D5E1DF8778F00E7C260 /* YGEnums.h */,
13687D5F1DF8778F00E7C260 /* YGMacros.h */,
13687D601DF8778F00E7C260 /* YGNodeList.c */,
13687D611DF8778F00E7C260 /* YGNodeList.h */,
13687D621DF8778F00E7C260 /* Yoga.c */,
13687D631DF8778F00E7C260 /* Yoga.h */,
);
name = yoga;
path = ../../yoga;
sourceTree = "<group>";
};
13687D641DF8778F00E7C260 /* YogaKit */ = {
isa = PBXGroup;
children = (
13687D691DF8778F00E7C260 /* UIView+Yoga.h */,
13687D6A1DF8778F00E7C260 /* UIView+Yoga.m */,
);
name = YogaKit;
path = ..;
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 */
@@ -164,11 +164,14 @@
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 = (
);
@@ -179,19 +182,43 @@
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 = 0810;
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" */;
@@ -208,6 +235,7 @@
projectRoot = "";
targets = (
13687D421DF8748300E7C260 /* YogaKitSample */,
638A944E1E215CC800A726AD /* YogaKitSampleTests */,
);
};
/* End PBXProject section */
@@ -221,24 +249,93 @@
);
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 = (
13687D801DF87CEC00E7C260 /* UIView+Yoga.m in Sources */,
13687D4E1DF8748400E7C260 /* ViewController.m in Sources */,
13687D4B1DF8748400E7C260 /* AppDelegate.m in Sources */,
13687D821DF87CF200E7C260 /* Yoga.c in Sources */,
13687D811DF87CF200E7C260 /* YGNodeList.c in Sources */,
13687D481DF8748400E7C260 /* main.m in Sources */,
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;
@@ -258,6 +355,7 @@
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;
@@ -305,6 +403,7 @@
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;
@@ -330,23 +429,60 @@
};
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;
};
@@ -369,6 +505,16 @@
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 */
};

View 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>

View File

@@ -1,16 +0,0 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@@ -1,27 +0,0 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = [ViewController new];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
@end

View File

@@ -0,0 +1,27 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
import Foundation
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func applicationDidFinishLaunching(_ application: UIApplication) {
self.window = UIWindow(frame: UIScreen.main.bounds)
if let window = self.window {
let navigationController = UINavigationController(rootViewController: ExamplesViewController())
navigationController.navigationBar.isTranslucent = false
window.rootViewController = navigationController
window.backgroundColor = .white
window.makeKeyAndVisible()
}
}
}

View File

@@ -1,43 +1,69 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Yoga-20x20@2x.png",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Yoga-20x20@3x.png",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
"idiom" : "iphone",
"filename" : "Yoga-29x29@1x.png",
"scale" : "1x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"filename" : "Yoga-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"size" : "40x40",
"filename" : "Yoga-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"size" : "60x60",
"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"
}
],

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,100 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
import UIKit
import IGListKit
private final class ExampleModel {
let title: String
let controllerClass: UIViewController.Type
init(title: String, controllerClass: UIViewController.Type) {
self.title = title
self.controllerClass = controllerClass
}
}
extension ExampleModel: IGListDiffable {
fileprivate func diffIdentifier() -> NSObjectProtocol {
return title as NSString
}
fileprivate func isEqual(toDiffableObject object: IGListDiffable?) -> Bool {
guard let otherObj = object as? ExampleModel else { return false }
return (title == otherObj.title) &&
(controllerClass == otherObj.controllerClass)
}
}
final class ExamplesViewController: UIViewController, IGListAdapterDataSource, IGListSingleSectionControllerDelegate {
private lazy var adapter: IGListAdapter = {
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
}()
private let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
// Update this to array to create more examples.
private let models: [ExampleModel] = [ExampleModel(title: "Basic Layout", controllerClass: BasicViewController.self),
ExampleModel(title: "Exclude Views in Layout", controllerClass: LayoutInclusionViewController.self)]
//MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
title = "Examples"
view.addSubview(collectionView)
adapter.collectionView = collectionView
adapter.dataSource = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.frame = view.bounds
}
//MARK: IGListAdapterDataSource
func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
return models as [IGListDiffable]
}
func listAdapter(_ listAdapter: IGListAdapter, sectionControllerFor object: Any) -> IGListSectionController {
let sizeBlock: IGListSingleSectionCellSizeBlock = { (model, context) in
return CGSize(width: (context?.containerSize.width)!, height: 75.0)
}
let configureBlock: IGListSingleSectionCellConfigureBlock = { (model, cell) in
guard let m = model as? ExampleModel, let c = cell as? SingleLabelCollectionCell else {
return
}
c.label.text = m.title
}
let sectionController = IGListSingleSectionController(cellClass: SingleLabelCollectionCell.self,
configureBlock: configureBlock,
sizeBlock: sizeBlock)
sectionController.selectionDelegate = self
return sectionController
}
func emptyView(for listAdapter: IGListAdapter) -> UIView? { return nil }
//MARK: IGListSingleSectionControllerDelegate
func didSelect(_ sectionController: IGListSingleSectionController) {
let section = adapter.section(for: sectionController)
let model = models[section]
let controller = model.controllerClass.init()
controller.title = model.title
self.navigationController?.pushViewController(controller, animated: true)
}
}

View File

@@ -0,0 +1,66 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
import UIKit
import IGListKit
import YogaKit
struct DemoItem {
let name: String
}
final class SwiftViewController: UIViewController, IGListAdapterDataSource {
lazy var adapter: IGListAdapter = {
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
}()
let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
//MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
title = "YogaKit Examples"
view.addSubview(collectionView)
adapter.collectionView = collectionView
adapter.dataSource = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.frame = view.bounds
}
//MARK: IGListAdapterDataSource
func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
return ["Dustin" as IGListDiffable, "Ryan" as IGListDiffable]
}
func listAdapter(_ listAdapter: IGListAdapter, sectionControllerFor object: Any) -> IGListSectionController {
let sizeBlock: IGListSingleSectionCellSizeBlock = { (model, context) in
return CGSize(width: (context?.containerSize.width)!, height: 100.0)
}
let configureBlock: IGListSingleSectionCellConfigureBlock = { (model, cell) in
guard let m = model as? String else {
return
}
cell.backgroundColor = (m == "Dustin") ? .blue : .red
}
return IGListSingleSectionController(cellClass: UICollectionViewCell.self,
configureBlock: configureBlock,
sizeBlock: sizeBlock)
}
func emptyView(for listAdapter: IGListAdapter) -> UIView? {
return nil
}
}

View File

@@ -1,15 +0,0 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

View File

@@ -10,27 +10,23 @@
#import <YogaKit/UIView+Yoga.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
UIView *root = self.view;
root.backgroundColor = [UIColor redColor];
[root yg_setUsesYoga:YES];
[root yg_setWidth:self.view.bounds.size.width];
[root yg_setHeight:self.view.bounds.size.height];
[root yg_setAlignItems:YGAlignCenter];
[root yg_setJustifyContent:YGJustifyCenter];
root.yoga.isEnabled = YES;
root.yoga.width = self.view.bounds.size.width;
root.yoga.height = self.view.bounds.size.height;
root.yoga.alignItems = YGAlignCenter;
root.yoga.justifyContent = YGJustifyCenter;
UIView *child1 = [UIView new];
child1.backgroundColor = [UIColor blueColor];
[child1 yg_setUsesYoga:YES];
[child1 yg_setWidth:100];
[child1 yg_setHeight:100];
child1.yoga.isEnabled = YES;
child1.yoga.width = 100;
child1.yoga.height = 100;
UIView *child2 = [UIView new];
child2.backgroundColor = [UIColor greenColor];
@@ -53,7 +49,7 @@
[child2 addSubview:child3];
[root addSubview:child1];
[root addSubview:child2];
[root yg_applyLayout];
[root.yoga applyLayoutPreservingOrigin:NO];
}

View File

@@ -0,0 +1,48 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
import UIKit
import YogaKit
final class BasicViewController: UIViewController {
override func viewDidLoad() {
let containerSize = self.view.bounds.size
let root = self.view!
root.backgroundColor = .white
root.yoga.isEnabled = true
root.yoga.width = containerSize.width
root.yoga.height = containerSize.height
root.yoga.alignItems = .center
root.yoga.justifyContent = .center
let child1 = UIView()
child1.backgroundColor = .blue
child1.yoga.isEnabled = true
child1.yoga.width = 100
child1.yoga.height = 10
child1.yoga.marginBottom = 25
root.addSubview(child1)
let child2 = UIView()
child2.yoga.isEnabled = true
child2.yoga.alignSelf = .flexEnd
child2.backgroundColor = .green
child2.frame = CGRect(x: 0, y: 0, width: 200, height: 100)
root.addSubview(child2)
let child3 = UIView()
child3.yoga.isEnabled = true
child3.yoga.alignSelf = .flexStart
child3.backgroundColor = .yellow
child3.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
root.addSubview(child3)
root.yoga.applyLayout(preservingOrigin: true)
}
}

View File

@@ -0,0 +1,70 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
import UIKit
import YogaKit
final class LayoutInclusionViewController: UIViewController {
private let button: UIButton = UIButton(type: .system)
private let disappearingView: UIView = UIView(frame: .zero)
private let contentView: UIView = UIView(frame: .zero)
override func viewDidLoad() {
let root = self.view!
root.backgroundColor = .white
root.yoga.isEnabled = true
root.yoga.flexDirection = .column
root.yoga.justifyContent = .spaceAround
contentView.backgroundColor = .clear
contentView.layer.borderColor = UIColor.lightGray.cgColor
contentView.layer.borderWidth = 1.0
contentView.yoga.isEnabled = true
contentView.yoga.height = 300
contentView.yoga.width = self.view.bounds.size.width
contentView.yoga.flexDirection = .row
contentView.yoga.justifyContent = .center
contentView.yoga.paddingHorizontal = 25
self.view.addSubview(contentView)
let redView = UIView(frame: .zero)
redView.backgroundColor = .red
redView.yoga.isEnabled = true
redView.yoga.flexGrow = 1
redView.yoga.flexShrink = 1
contentView.addSubview(redView)
disappearingView.backgroundColor = .blue
disappearingView.yoga.isEnabled = true
disappearingView.yoga.flexGrow = 1
contentView.addSubview(disappearingView)
button.setTitle("Add Blue View", for: UIControlState.selected)
button.setTitle("Remove Blue View", for: UIControlState.normal)
button.addTarget(self, action: #selector(buttonWasTapped), for: UIControlEvents.touchUpInside)
button.yoga.isEnabled = true
button.yoga.height = 300
button.yoga.width = 300
button.yoga.alignSelf = .center
root.addSubview(button)
root.yoga.applyLayout(preservingOrigin: false)
}
// MARK - UIButton Action
func buttonWasTapped() {
button.isSelected = !button.isSelected
button.isUserInteractionEnabled = false
disappearingView.yoga.isIncludedInLayout = !disappearingView.yoga.isIncludedInLayout
disappearingView.isHidden = !disappearingView.isHidden
contentView.yoga.applyLayout(preservingOrigin: true)
button.isUserInteractionEnabled = true
}
}

View File

@@ -0,0 +1,45 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
import UIKit
import YogaKit
final class SingleLabelCollectionCell: UICollectionViewCell {
let label: UILabel = UILabel(frame: .zero)
override init(frame: CGRect) {
super.init(frame: frame)
contentView.yoga.isEnabled = true
contentView.yoga.flexDirection = .column
contentView.yoga.justifyContent = .flexEnd
label.textAlignment = .center
label.numberOfLines = 1
label.yoga.isIncludedInLayout = false
contentView.addSubview(label)
let border = UIView(frame: .zero)
border.backgroundColor = .lightGray
border.yoga.isEnabled = true
border.yoga.height = 0.5
border.yoga.marginHorizontal = 25
contentView.addSubview(border)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
contentView.yoga.applyLayout(preservingOrigin: false)
label.frame = contentView.bounds
}
}

View File

@@ -1,16 +0,0 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

36
android/BUCK Normal file
View File

@@ -0,0 +1,36 @@
# Copyright (c) 2014-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
include_defs("//YOGA_DEFS")
android_aar(
name = "android",
manifest_skeleton = "src/main/AndroidManifest.xml",
visibility = [
"PUBLIC",
],
deps = [
ANDROID_JAVA_TARGET,
ANDROID_RES_TARGET,
INFER_ANNOTATIONS_TARGET,
JAVA_TARGET,
PROGRUARD_ANNOTATIONS_TARGET,
],
)
android_resource(
name = "res",
package = "com.facebook.yoga.android",
res = "src/main/res",
visibility = [
"PUBLIC",
],
)
project_config(
src_target = ":android",
)

52
android/build.gradle Normal file
View File

@@ -0,0 +1,52 @@
apply plugin: "com.jfrog.bintray"
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'maven-publish'
targetCompatibility = '1.7'
sourceCompatibility = '1.7'
version = '1.2.0'
group = 'com.facebook.yoga.android'
android {
compileSdkVersion 19
buildToolsVersion "19.1.0"
defaultConfig {
minSdkVersion 15
targetSdkVersion 19
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
dependencies {
compile 'com.facebook.yoga:yoga:1.2.0'
}
task sourcesJar(type: Jar) {
classifier = 'source'
from android.sourceSets.main.java.srcDirs
}
task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
ext {
bintrayName = "com.facebook.yoga.android:yoga-layout"
}
apply from: rootProject.file('gradle/android-jcenter-install.gradle')

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2014-present, Facebook, Inc.
All rights reserved.
This source code is licensed under the license found in the
LICENSE-examples file in the root directory of this source tree.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.facebook.samples.yoga"
android:versionCode="1"
android:versionName="1.0"
>
<variable name="applicationId" value="com.facebook.yoga"/>
<variable name="app_label" value="Yoga Sample App"/>
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="19"
/>
<application
android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:allowBackup="false"
android:theme="@style/NoTitleBarWhiteBG"
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>
</application>
</manifest>

39
android/sample/BUCK Normal file
View File

@@ -0,0 +1,39 @@
# Copyright 2014-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the license found in the
# LICENSE-examples file in the root directory of this source tree.
include_defs("//YOGA_DEFS")
android_binary(
name = "sample",
keystore = ":debug_keystore",
manifest = "AndroidManifest.xml",
deps = [
ANDROID_SAMPLE_JAVA_TARGET,
ANDROID_SAMPLE_RES_TARGET,
],
)
android_resource(
name = "res",
package = "com.facebook.samples.yoga",
res = "res",
visibility = [
"PUBLIC",
],
deps = [
ANDROID_RES_TARGET,
],
)
keystore(
name = "debug_keystore",
properties = "debug.keystore.properties",
store = "debug.keystore",
)
project_config(
src_target = ":sample",
)

Binary file not shown.

View File

@@ -0,0 +1,3 @@
key.alias=androiddebugkey
key.store.password=android
key.alias.password=android

View File

@@ -0,0 +1,23 @@
# Copyright (c) 2014-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
include_defs("//YOGA_DEFS")
android_library(
name = "yoga",
srcs = glob(["**/*.java"]),
visibility = [
"PUBLIC",
],
deps = [
ANDROID_JAVA_TARGET,
ANDROID_SAMPLE_RES_TARGET,
ANDROID_SUPPORT_TARGET,
APPCOMPAT_TARGET,
SOLOADER_TARGET,
],
)

View File

@@ -0,0 +1,34 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
package com.facebook.samples.yoga;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import com.facebook.samples.yoga.R;
import com.facebook.soloader.SoLoader;
import com.facebook.yoga.android.YogaViewLayoutFactory;
/**
* An activity to show off Yoga in Android. This activity shows a simple layout (defined in
* {@code main_layout.xml}) that shows off the awesome functionality of the Yoga layout engine
* as well as some optimisations on layout systems that it facilitates.
*/
public class MainActivity extends ActionBarActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
LayoutInflater.from(this).setFactory(YogaViewLayoutFactory.getInstance());
super.onCreate(savedInstanceState);
SoLoader.init(this, false);
setContentView(R.layout.main_layout);
}
}

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View 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>

View 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_margin_horizontal="10dp"
yoga:yg_margin_top="5dp"
yoga:yg_flex_direction="row"
yoga:yg_align_items="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_margin_start="8dp"
/>
</YogaLayout>
<YogaLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sample_children_background"
yoga:yg_margin_horizontal="10dp"
yoga:yg_margin_top="5dp"
yoga:yg_flex_direction="row"
yoga:yg_align_items="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_margin_start="8dp"
/>
</YogaLayout>
<YogaLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sample_children_background"
yoga:yg_margin_horizontal="10dp"
yoga:yg_margin_top="5dp"
yoga:yg_flex_direction="row"
yoga:yg_align_items="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_margin_start="8dp"
/>
</YogaLayout>
<YogaLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sample_children_background"
yoga:yg_margin_horizontal="10dp"
yoga:yg_margin_top="5dp"
yoga:yg_flex_direction="row"
yoga:yg_align_items="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_margin_start="8dp"
/>
</YogaLayout>
<YogaLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sample_children_background"
yoga:yg_margin_horizontal="10dp"
yoga:yg_margin_top="5dp"
yoga:yg_flex_direction="row"
yoga:yg_align_items="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_margin_start="10dp"
/>
</YogaLayout>
</YogaLayout>

View 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>

View 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>

View 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>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014-present, Facebook, Inc.
All rights reserved.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree. An additional grant
of patent rights can be found in the PATENTS file in the same directory.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.facebook.yoga.android"
android:versionCode="1"
android:versionName="1.0"
>
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="21"
/>
<application/>
</manifest>

View File

@@ -0,0 +1,23 @@
# Copyright (c) 2014-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
include_defs("//YOGA_DEFS")
android_library(
name = "android",
srcs = glob(["**/*.java"]),
visibility = [
"PUBLIC",
],
deps = [
ANDROID_RES_TARGET,
INFER_ANNOTATIONS_TARGET,
JAVA_TARGET,
JSR_305_TARGET,
SOLOADER_TARGET,
],
)

View File

@@ -0,0 +1,150 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.yoga.android;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import com.facebook.yoga.YogaNode;
/**
* Much like a {@link YogaLayout}, except this class does not render itself (the container) to the
* screen. As a result, <i>do not use this if you wish the container to have a background or
* foreground</i>. However, all of its children will still render as expected.
*
* <p>
* In practice, this class never added to the View tree, and all its children become children of its
* parent. As a result, all the layout (such as the traversal of the tree) is performed by Yoga
* (and so natively) increasing performance.
*/
public class VirtualYogaLayout extends ViewGroup {
final private List<View> mChildren = new LinkedList<>();
final private Map<View, YogaNode> mYogaNodes = new HashMap<>();
final private YogaNode mYogaNode = new YogaNode();
public VirtualYogaLayout(Context context) {
super(context);
}
public VirtualYogaLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public VirtualYogaLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
YogaLayout.LayoutParams lp = new YogaLayout.LayoutParams(context, attrs);
YogaLayout.applyLayoutParams(lp, mYogaNode, this);
}
public YogaNode getYogaNode() {
return mYogaNode;
}
/**
* Called to add a view, creating a new yoga node for it and adding that yoga node to the parent.
* If the child is a {@link VirtualYogaLayout}, we simply transfer all its children to this one
* in a manner that maintains the tree, and add its root to the tree.
*
* @param child the View to add
* @param index the position at which to add it (ignored)
* @param params the layout parameters to apply
*/
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (child instanceof VirtualYogaLayout) {
((VirtualYogaLayout) child).transferChildren(this);
final YogaNode childNode = ((VirtualYogaLayout) child).getYogaNode();
mYogaNode.addChildAt(childNode, mYogaNode.getChildCount());
return;
}
YogaNode node = new YogaNode();
YogaLayout.LayoutParams lp = new YogaLayout.LayoutParams(params);
YogaLayout.applyLayoutParams(lp, node, child);
node.setData(child);
node.setMeasureFunction(new YogaLayout.ViewMeasureFunction());
mYogaNode.addChildAt(node, mYogaNode.getChildCount());
addView(child, node);
}
/**
* Called to add a view with a corresponding node, but not to change the Yoga tree in any way.
*
* @param child the View to add
* @param node the corresponding yoga node
*/
public void addView(View child, YogaNode node) {
mChildren.add(child);
mYogaNodes.put(child, node);
}
/**
* Gives up children {@code View}s to the parent, maintaining the Yoga tree. This function calls
* {@link YogaLayout#addView(View, YogaNode)} or {@link VirtualYogaLayout#addView(View, YogaNode)}
* on the parent to add the {@code View} without generating new yoga nodes.
*
* @param parent the parent to pass children to (must be a YogaLayout or a VirtualYogaLayout)
*/
protected void transferChildren(ViewGroup parent) {
if (parent instanceof VirtualYogaLayout) {
for (View child : mChildren) {
((VirtualYogaLayout) parent).addView(child, mYogaNodes.get(child));
}
} else if (parent instanceof YogaLayout) {
for (View child : mChildren) {
((YogaLayout) parent).addView(child, mYogaNodes.get(child));
}
} else {
throw new RuntimeException("VirtualYogaLayout cannot transfer children to ViewGroup of type "
+parent.getClass().getCanonicalName()+". Must either be a VirtualYogaLayout or a " +
"YogaLayout.");
}
mChildren.clear();
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
throw new RuntimeException("Attempting to layout a VirtualYogaLayout");
}
@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new YogaLayout.LayoutParams(getContext(), attrs);
}
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new YogaLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
}
@Override
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new YogaLayout.LayoutParams(p);
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof YogaLayout.LayoutParams;
}
}

View File

@@ -0,0 +1,814 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.yoga.android;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import com.facebook.yoga.android.R;
import com.facebook.yoga.YogaAlign;
import com.facebook.yoga.YogaConstants;
import com.facebook.yoga.YogaDirection;
import com.facebook.yoga.YogaDisplay;
import com.facebook.yoga.YogaEdge;
import com.facebook.yoga.YogaFlexDirection;
import com.facebook.yoga.YogaJustify;
import com.facebook.yoga.YogaMeasureFunction;
import com.facebook.yoga.YogaMeasureMode;
import com.facebook.yoga.YogaMeasureOutput;
import com.facebook.yoga.YogaNode;
import com.facebook.yoga.YogaNodeAPI;
import com.facebook.yoga.YogaOverflow;
import com.facebook.yoga.YogaPositionType;
import com.facebook.yoga.YogaWrap;
/**
* A {@code ViewGroup} based on the Yoga layout engine.
*
* <p>
* This class is designed to be as "plug and play" as possible. That is, you can use it in XML
* like this (note: to use {@code YogaLayout} you need to use the {@link YogaViewLayoutFactory}):
* <p>
* <pre>{@code
* <YogaLayout
* xmlns:android="http://schemas.android.com/apk/res/android"
* xmlns:yoga="http://schemas.android.com/lib/com.facebook.yoga.android"
* android:layout_width="match_parent"
* android:layout_height="match_parent"
* yoga:flex_direction="row"
* yoga:padding_all="10dp"
* >
* <TextView
* android:layout_width="match_parent"
* android:layout_height="match_parent"
* android:text="Hello, World!"
* yoga:flex="1"
* />
* </YogaLayout>
* }</pre>
*
* Under the hood, all views added to this {@code ViewGroup} are laid out using flexbox rules
* and the Yoga engine.
*/
public class YogaLayout extends ViewGroup {
private final Map<View, YogaNode> mYogaNodes;
private final YogaNode mYogaNode;
public YogaLayout(Context context) {
this(context, null, 0);
}
public YogaLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public YogaLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mYogaNode = new YogaNode();
mYogaNodes = new HashMap<>();
mYogaNode.setData(this);
mYogaNode.setMeasureFunction(new ViewMeasureFunction());
final LayoutParams layoutParams = new LayoutParams(context, attrs);
applyLayoutParams(layoutParams, mYogaNode, this);
}
YogaNode getYogaNode() {
return mYogaNode;
}
YogaNode getYogaNodeForView(View view) {
return mYogaNodes.get(view);
}
/**
* Adds a child view with the specified layout parameters.
*
* In the typical View is added, this constructs a {@code YogaNode} for this child and applies all
* the {@code yoga:*} attributes. The Yoga node is added to the Yoga tree and the child is added
* to this ViewGroup.
*
* If the child is a {@link YogaLayout} itself, we do not construct a new Yoga node for that
* child, but use its root node instead.
*
* If the child is a {@link VirtualYogaLayout}, we also use its Yoga node, but we also instruct it
* to transfer all of its children to this {@link YogaLayout} while preserving the Yoga tree (so
* that the layout of its children is correct). The {@link VirtualYogaLayout} is then not added
* to the View hierarchy.
*
* <p><strong>Note:</strong> do not invoke this method from
* {@code #draw(android.graphics.Canvas)}, {@code onDraw(android.graphics.Canvas)},
* {@code #dispatchDraw(android.graphics.Canvas)} or any related method.</p>
*
* @param child the child view to add
* @param index the position at which to add the child or -1 to add last
* @param params the layout parameters to set on the child
*/
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
// Internal nodes (which this is now) cannot have measure functions
mYogaNode.setMeasureFunction(null);
if (child instanceof VirtualYogaLayout) {
((VirtualYogaLayout) child).transferChildren(this);
final YogaNode childNode = ((VirtualYogaLayout) child).getYogaNode();
mYogaNode.addChildAt(childNode, mYogaNode.getChildCount());
return;
}
super.addView(child, index, params);
// It is possible that addView is being called as part of a transferal of children, in which
// case we already know about the YogaNode and only need the Android View tree to be aware
// that we now own this child. If so, we don't need to do anything further
if (mYogaNodes.containsKey(child)) {
return;
}
YogaNode childNode;
if (child instanceof YogaLayout) {
childNode = ((YogaLayout) child).getYogaNode();
} else {
childNode = new YogaNode();
childNode.setData(child);
childNode.setMeasureFunction(new ViewMeasureFunction());
}
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
applyLayoutParams(lp, childNode, child);
mYogaNodes.put(child, childNode);
mYogaNode.addChildAt(childNode, mYogaNode.getChildCount());
}
/**
* Adds a view to this {@code ViewGroup} with an already given {@code YogaNode}. Use
* this function if you already have a Yoga node (and perhaps tree) associated with the view you
* are adding, that you would like to preserve.
*
* @param child The view to add
* @param node The Yoga node belonging to the view
*/
public void addView(View child, YogaNode node) {
mYogaNodes.put(child, node);
addView(child);
}
@Override
public void removeView(View view) {
removeViewFromYogaTree(view, false);
super.removeView(view);
}
@Override
public void removeViewAt(int index) {
removeViewFromYogaTree(getChildAt(index), false);
super.removeViewAt(index);
}
@Override
public void removeViewInLayout(View view) {
removeViewFromYogaTree(view, true);
super.removeViewInLayout(view);
}
@Override
public void removeViews(int start, int count) {
for (int i = start; i < start + count; i++) {
removeViewFromYogaTree(getChildAt(i), false);
}
super.removeViews(start, count);
}
@Override
public void removeViewsInLayout(int start, int count) {
for (int i = start; i < start + count; i++) {
removeViewFromYogaTree(getChildAt(i), true);
}
super.removeViewsInLayout(start, count);
}
@Override
public void removeAllViews() {
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
removeViewFromYogaTree(getChildAt(i), false);
}
super.removeAllViews();
}
@Override
public void removeAllViewsInLayout() {
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
removeViewFromYogaTree(getChildAt(i), true);
}
super.removeAllViewsInLayout();
}
/**
* Marks a particular view as "dirty" and to be relaid out. If the view is not a child of this
* {@link YogaLayout}, the entire tree is traversed to find it.
*
* @param view the view to mark as dirty
*/
public void invalidate(View view) {
if (mYogaNodes.containsKey(view)) {
mYogaNodes.get(view).dirty();
return;
}
final int childCount = mYogaNode.getChildCount();
for (int i = 0; i < childCount; i++) {
final YogaNode yogaNode = mYogaNode.getChildAt(i);
if (yogaNode.getData() instanceof YogaLayout) {
((YogaLayout) yogaNode.getData()).invalidate(view);
}
}
invalidate();
}
private void removeViewFromYogaTree(View view, boolean inLayout) {
final YogaNode node = mYogaNodes.get(view);
if (node == null) {
return;
}
final YogaNode parent = node.getParent();
for (int i = 0; i < parent.getChildCount(); i++) {
if (parent.getChildAt(i).equals(node)) {
parent.removeChildAt(i);
break;
}
}
node.setData(null);
mYogaNodes.remove(view);
if (inLayout) {
mYogaNode.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
}
}
private void applyLayoutRecursive(YogaNode node, float xOffset, float yOffset) {
View view = (View) node.getData();
if (view != null && view != this) {
if (view.getVisibility() == GONE) {
return;
}
view.measure(
View.MeasureSpec.makeMeasureSpec(
Math.round(node.getLayoutWidth()),
View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(
Math.round(node.getLayoutHeight()),
View.MeasureSpec.EXACTLY));
view.layout(
Math.round(xOffset + node.getLayoutX()),
Math.round(yOffset + node.getLayoutY()),
Math.round(xOffset + node.getLayoutX() + node.getLayoutWidth()),
Math.round(yOffset + node.getLayoutY() + node.getLayoutHeight()));
}
final int childrenCount = node.getChildCount();
for (int i = 0; i < childrenCount; i++) {
if (this.equals(view)) {
applyLayoutRecursive(node.getChildAt(i), xOffset, yOffset);
} else if (view instanceof YogaLayout) {
continue;
} else {
applyLayoutRecursive(
node.getChildAt(i),
xOffset + node.getLayoutX(),
yOffset + node.getLayoutY());
}
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// Either we are a root of a tree, or this function is called by our parent's onLayout, in which
// case our r-l and b-t are the size of our node.
if (!(getParent() instanceof YogaLayout)) {
createLayout(
MeasureSpec.makeMeasureSpec(r - l, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(b - t, MeasureSpec.EXACTLY));
}
applyLayoutRecursive(mYogaNode, 0, 0);
}
/**
* This function is mostly unneeded, because Yoga is doing the measuring. Hence we only need to
* return accurate results if we are the root.
*
* @param widthMeasureSpec the suggested specification for the width
* @param heightMeasureSpec the suggested specification for the height
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!(getParent() instanceof YogaLayout)) {
createLayout(widthMeasureSpec, heightMeasureSpec);
}
setMeasuredDimension(
Math.round(mYogaNode.getLayoutWidth()),
Math.round(mYogaNode.getLayoutHeight()));
}
private void createLayout(int widthMeasureSpec, int heightMeasureSpec) {
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
mYogaNode.setHeight(heightSize);
}
if (widthMode == MeasureSpec.EXACTLY) {
mYogaNode.setWidth(widthSize);
}
if (heightMode == MeasureSpec.AT_MOST) {
mYogaNode.setMaxHeight(heightSize);
}
if (widthMode == MeasureSpec.AT_MOST) {
mYogaNode.setMaxWidth(widthSize);
}
mYogaNode.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
}
/**
* Applies the layout parameters to the YogaNode. That is, this function is a translator from
* {@code yoga:X="Y"} to {@code yogaNode.setX(Y);}, with some reasonable defaults.
*
* <p>
* If the SDK version is high enough, and the {@code yoga:direction} is not set on
* the component, the direction (LTR or RTL) is set according to the locale.
*
* <p>
* The attributes {@code padding_top}, {@code padding_right} etc. default to those of the view's
* drawable background, if it has one.
*
* @param layoutParameters The source set of params
* @param node The destination node
*/
protected static void applyLayoutParams(LayoutParams layoutParameters, YogaNode node, View view) {
// JELLY_BEAN_MR1 (17) is the first version supporting getLayoutDirection()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Configuration configuration = view.getResources().getConfiguration();
if (configuration.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
node.setDirection(YogaDirection.RTL);
}
}
Drawable background = view.getBackground();
if (background != null) {
final Rect backgroundPadding = new Rect();
if (background.getPadding(backgroundPadding)) {
node.setPadding(YogaEdge.LEFT, backgroundPadding.left);
node.setPadding(YogaEdge.TOP, backgroundPadding.top);
node.setPadding(YogaEdge.RIGHT, backgroundPadding.right);
node.setPadding(YogaEdge.BOTTOM, backgroundPadding.bottom);
}
}
for (int i = 0; i < layoutParameters.numericAttributes.size(); i++) {
final int attribute = layoutParameters.numericAttributes.keyAt(i);
final float value = layoutParameters.numericAttributes.valueAt(i);
if (attribute == R.styleable.yoga_yg_align_content) {
node.setAlignContent(YogaAlign.fromInt(Math.round(value)));
} else if (attribute == R.styleable.yoga_yg_align_items) {
node.setAlignItems(YogaAlign.fromInt(Math.round(value)));
} else if (attribute == R.styleable.yoga_yg_align_self) {
node.setAlignSelf(YogaAlign.fromInt(Math.round(value)));
} else if (attribute == R.styleable.yoga_yg_aspect_ratio) {
node.setAspectRatio(value);
} else if (attribute == R.styleable.yoga_yg_border_left) {
node.setBorder(YogaEdge.LEFT, value);
} else if (attribute == R.styleable.yoga_yg_border_top) {
node.setBorder(YogaEdge.TOP, value);
} else if (attribute == R.styleable.yoga_yg_border_right) {
node.setBorder(YogaEdge.RIGHT, value);
} else if (attribute == R.styleable.yoga_yg_border_bottom) {
node.setBorder(YogaEdge.BOTTOM, value);
} else if (attribute == R.styleable.yoga_yg_border_start) {
node.setBorder(YogaEdge.START, value);
} else if (attribute == R.styleable.yoga_yg_border_end) {
node.setBorder(YogaEdge.END, value);
} else if (attribute == R.styleable.yoga_yg_border_horizontal) {
node.setBorder(YogaEdge.HORIZONTAL, value);
} else if (attribute == R.styleable.yoga_yg_border_vertical) {
node.setBorder(YogaEdge.VERTICAL, value);
} else if (attribute == R.styleable.yoga_yg_border_all) {
node.setBorder(YogaEdge.ALL, value);
} else if (attribute == R.styleable.yoga_yg_direction) {
node.setDirection(YogaDirection.fromInt(Math.round(value)));
} else if (attribute == R.styleable.yoga_yg_display) {
node.setDisplay(YogaDisplay.fromInt(Math.round(value)));
} else if (attribute == R.styleable.yoga_yg_flex) {
node.setFlex(value);
} else if (attribute == R.styleable.yoga_yg_flex_basis) {
node.setFlexBasis(value);
} else if (attribute == R.styleable.yoga_yg_flex_direction) {
node.setFlexDirection(YogaFlexDirection.fromInt(Math.round(value)));
} else if (attribute == R.styleable.yoga_yg_flex_grow) {
node.setFlexGrow(value);
} else if (attribute == R.styleable.yoga_yg_flex_shrink) {
node.setFlexShrink(value);
} else if (attribute == R.styleable.yoga_yg_height) {
node.setHeight(value);
} else if (attribute == R.styleable.yoga_yg_margin_left) {
node.setMargin(YogaEdge.LEFT, value);
} else if (attribute == R.styleable.yoga_yg_justify_content) {
node.setJustifyContent(YogaJustify.fromInt(Math.round(value)));
} else if (attribute == R.styleable.yoga_yg_margin_top) {
node.setMargin(YogaEdge.TOP, value);
} else if (attribute == R.styleable.yoga_yg_margin_right) {
node.setMargin(YogaEdge.RIGHT, value);
} else if (attribute == R.styleable.yoga_yg_margin_bottom) {
node.setMargin(YogaEdge.BOTTOM, value);
} else if (attribute == R.styleable.yoga_yg_margin_start) {
node.setMargin(YogaEdge.START, value);
} else if (attribute == R.styleable.yoga_yg_margin_end) {
node.setMargin(YogaEdge.END, value);
} else if (attribute == R.styleable.yoga_yg_margin_horizontal) {
node.setMargin(YogaEdge.HORIZONTAL, value);
} else if (attribute == R.styleable.yoga_yg_margin_vertical) {
node.setMargin(YogaEdge.VERTICAL, value);
} else if (attribute == R.styleable.yoga_yg_margin_all) {
node.setMargin(YogaEdge.ALL, value);
} else if (attribute == R.styleable.yoga_yg_max_height) {
node.setMaxHeight(value);
} else if (attribute == R.styleable.yoga_yg_max_width) {
node.setMaxWidth(value);
} else if (attribute == R.styleable.yoga_yg_min_height) {
node.setMinHeight(value);
} else if (attribute == R.styleable.yoga_yg_min_width) {
node.setMinWidth(value);
} else if (attribute == R.styleable.yoga_yg_overflow) {
node.setOverflow(YogaOverflow.fromInt(Math.round(value)));
} else if (attribute == R.styleable.yoga_yg_padding_left) {
node.setPadding(YogaEdge.LEFT, value);
} else if (attribute == R.styleable.yoga_yg_padding_top) {
node.setPadding(YogaEdge.TOP, value);
} else if (attribute == R.styleable.yoga_yg_padding_right) {
node.setPadding(YogaEdge.RIGHT, value);
} else if (attribute == R.styleable.yoga_yg_padding_bottom) {
node.setPadding(YogaEdge.BOTTOM, value);
} else if (attribute == R.styleable.yoga_yg_padding_start) {
node.setPadding(YogaEdge.START, value);
} else if (attribute == R.styleable.yoga_yg_padding_end) {
node.setPadding(YogaEdge.END, value);
} else if (attribute == R.styleable.yoga_yg_padding_horizontal) {
node.setPadding(YogaEdge.HORIZONTAL, value);
} else if (attribute == R.styleable.yoga_yg_padding_vertical) {
node.setPadding(YogaEdge.VERTICAL, value);
} else if (attribute == R.styleable.yoga_yg_padding_all) {
node.setPadding(YogaEdge.ALL, value);
} else if (attribute == R.styleable.yoga_yg_position_left) {
node.setPosition(YogaEdge.LEFT, value);
} else if (attribute == R.styleable.yoga_yg_position_top) {
node.setPosition(YogaEdge.TOP, value);
} else if (attribute == R.styleable.yoga_yg_position_right) {
node.setPosition(YogaEdge.RIGHT, value);
} else if (attribute == R.styleable.yoga_yg_position_bottom) {
node.setPosition(YogaEdge.BOTTOM, value);
} else if (attribute == R.styleable.yoga_yg_position_start) {
node.setPosition(YogaEdge.START, value);
} else if (attribute == R.styleable.yoga_yg_position_end) {
node.setPosition(YogaEdge.END, value);
} else if (attribute == R.styleable.yoga_yg_position_horizontal) {
node.setPosition(YogaEdge.HORIZONTAL, value);
} else if (attribute == R.styleable.yoga_yg_position_vertical) {
node.setPosition(YogaEdge.VERTICAL, value);
} else if (attribute == R.styleable.yoga_yg_position_all) {
node.setPosition(YogaEdge.ALL, value);
} else if (attribute == R.styleable.yoga_yg_position_type) {
node.setPositionType(YogaPositionType.fromInt(Math.round(value)));
} else if (attribute == R.styleable.yoga_yg_width) {
node.setWidth(value);
} else if (attribute == R.styleable.yoga_yg_wrap) {
node.setWrap(YogaWrap.fromInt(Math.round(value)));
}
}
for (int i = 0; i < layoutParameters.stringAttributes.size(); i++) {
final int attribute = layoutParameters.stringAttributes.keyAt(i);
final String value = layoutParameters.stringAttributes.valueAt(i);
if (value.equals("auto")) {
if (attribute == R.styleable.yoga_yg_margin_left) {
node.setMarginAuto(YogaEdge.LEFT);
} else if (attribute == R.styleable.yoga_yg_margin_top) {
node.setMarginAuto(YogaEdge.TOP);
} else if (attribute == R.styleable.yoga_yg_margin_right) {
node.setMarginAuto(YogaEdge.RIGHT);
} else if (attribute == R.styleable.yoga_yg_margin_bottom) {
node.setMarginAuto(YogaEdge.BOTTOM);
} else if (attribute == R.styleable.yoga_yg_margin_start) {
node.setMarginAuto(YogaEdge.START);
} else if (attribute == R.styleable.yoga_yg_margin_end) {
node.setMarginAuto(YogaEdge.END);
} else if (attribute == R.styleable.yoga_yg_margin_horizontal) {
node.setMarginAuto(YogaEdge.HORIZONTAL);
} else if (attribute == R.styleable.yoga_yg_margin_vertical) {
node.setMarginAuto(YogaEdge.VERTICAL);
} else if (attribute == R.styleable.yoga_yg_margin_all) {
node.setMarginAuto(YogaEdge.ALL);
}
}
if (value.endsWith("%")) {
final float numericValue = Float.parseFloat(value.substring(0, value.length()-1));
if (attribute == R.styleable.yoga_yg_flex_basis) {
node.setFlexBasisPercent(numericValue);
} else if (attribute == R.styleable.yoga_yg_height) {
node.setHeightPercent(numericValue);
} else if (attribute == R.styleable.yoga_yg_margin_left) {
node.setMarginPercent(YogaEdge.LEFT, numericValue);
} else if (attribute == R.styleable.yoga_yg_margin_top) {
node.setMarginPercent(YogaEdge.TOP, numericValue);
} else if (attribute == R.styleable.yoga_yg_margin_right) {
node.setMarginPercent(YogaEdge.RIGHT, numericValue);
} else if (attribute == R.styleable.yoga_yg_margin_bottom) {
node.setMarginPercent(YogaEdge.BOTTOM, numericValue);
} else if (attribute == R.styleable.yoga_yg_margin_start) {
node.setMarginPercent(YogaEdge.START, numericValue);
} else if (attribute == R.styleable.yoga_yg_margin_end) {
node.setMarginPercent(YogaEdge.END, numericValue);
} else if (attribute == R.styleable.yoga_yg_margin_horizontal) {
node.setMarginPercent(YogaEdge.HORIZONTAL, numericValue);
} else if (attribute == R.styleable.yoga_yg_margin_vertical) {
node.setMarginPercent(YogaEdge.VERTICAL, numericValue);
} else if (attribute == R.styleable.yoga_yg_margin_all) {
node.setMarginPercent(YogaEdge.ALL, numericValue);
} else if (attribute == R.styleable.yoga_yg_max_height) {
node.setMaxHeightPercent(numericValue);
} else if (attribute == R.styleable.yoga_yg_max_width) {
node.setMaxWidthPercent(numericValue);
} else if (attribute == R.styleable.yoga_yg_min_height) {
node.setMinHeightPercent(numericValue);
} else if (attribute == R.styleable.yoga_yg_min_width) {
node.setMinWidthPercent(numericValue);
} else if (attribute == R.styleable.yoga_yg_padding_left) {
node.setPaddingPercent(YogaEdge.LEFT, numericValue);
} else if (attribute == R.styleable.yoga_yg_padding_top) {
node.setPaddingPercent(YogaEdge.TOP, numericValue);
} else if (attribute == R.styleable.yoga_yg_padding_right) {
node.setPaddingPercent(YogaEdge.RIGHT, numericValue);
} else if (attribute == R.styleable.yoga_yg_padding_bottom) {
node.setPaddingPercent(YogaEdge.BOTTOM, numericValue);
} else if (attribute == R.styleable.yoga_yg_padding_start) {
node.setPaddingPercent(YogaEdge.START, numericValue);
} else if (attribute == R.styleable.yoga_yg_padding_end) {
node.setPaddingPercent(YogaEdge.END, numericValue);
} else if (attribute == R.styleable.yoga_yg_padding_horizontal) {
node.setPaddingPercent(YogaEdge.HORIZONTAL, numericValue);
} else if (attribute == R.styleable.yoga_yg_padding_vertical) {
node.setPaddingPercent(YogaEdge.VERTICAL, numericValue);
} else if (attribute == R.styleable.yoga_yg_padding_all) {
node.setPaddingPercent(YogaEdge.ALL, numericValue);
} else if (attribute == R.styleable.yoga_yg_position_left) {
node.setPositionPercent(YogaEdge.LEFT, numericValue);
} else if (attribute == R.styleable.yoga_yg_position_top) {
node.setPositionPercent(YogaEdge.TOP, numericValue);
} else if (attribute == R.styleable.yoga_yg_position_right) {
node.setPositionPercent(YogaEdge.RIGHT, numericValue);
} else if (attribute == R.styleable.yoga_yg_position_bottom) {
node.setPositionPercent(YogaEdge.BOTTOM, numericValue);
} else if (attribute == R.styleable.yoga_yg_position_start) {
node.setPositionPercent(YogaEdge.START, numericValue);
} else if (attribute == R.styleable.yoga_yg_position_end) {
node.setPositionPercent(YogaEdge.END, numericValue);
} else if (attribute == R.styleable.yoga_yg_position_horizontal) {
node.setPositionPercent(YogaEdge.HORIZONTAL, numericValue);
} else if (attribute == R.styleable.yoga_yg_position_vertical) {
node.setPositionPercent(YogaEdge.VERTICAL, numericValue);
} else if (attribute == R.styleable.yoga_yg_position_all) {
node.setPositionPercent(YogaEdge.ALL, numericValue);
} else if (attribute == R.styleable.yoga_yg_width) {
node.setWidthPercent(numericValue);
}
}
}
}
@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new YogaLayout.LayoutParams(getContext(), attrs);
}
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new YogaLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
}
@Override
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new YogaLayout.LayoutParams(p);
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
/**
* {@code YogaLayout.LayoutParams} are used by views to tell {@link YogaLayout} how they want to
* be laid out. More precisely, the specify the yoga parameters of the view.
*
* <p>
* This is actually mostly a wrapper around a {@code SparseArray} that holds a mapping between
* styleable id's ({@code R.styleable.yoga_yg_*}) and the float of their values. In cases where
* the value is an enum or an integer, they should first be cast to int (with rounding) before
* using.
*/
public static class LayoutParams extends ViewGroup.LayoutParams {
/**
* A mapping from attribute keys ({@code R.styleable.yoga_yg_*}) to the float of their values.
* For attributes like position_percent_left (float), this is the native type. For attributes
* like align_self (enums), the integer enum value is cast (rounding is used on the other side
* to prevent precision errors). Dimension attributes are stored as float pixels.
*/
SparseArray<Float> numericAttributes;
/**
* A mapping from attribute keys ({@code R.styleable.yoga_yg_*}) with string values to those
* strings. This is used for values such as "auto".
*/
SparseArray<String> stringAttributes;
/**
* Constructs a set of layout params from a source set. In the case that the source set is
* actually a {@link YogaLayout.LayoutParams}, we can copy all the yoga attributes. Otherwise
* we start with a blank slate.
*
* @param source The layout params to copy from
*/
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
if (source instanceof LayoutParams) {
numericAttributes = ((LayoutParams) source).numericAttributes.clone();
stringAttributes = ((LayoutParams) source).stringAttributes.clone();
} else {
numericAttributes = new SparseArray<>();
stringAttributes = new SparseArray<>();
// Negative values include MATCH_PARENT and WRAP_CONTENT
if (source.width >= 0) {
numericAttributes.put(R.styleable.yoga_yg_width, (float) width);
}
if (source.height >= 0) {
numericAttributes.put(R.styleable.yoga_yg_height, (float) height);
}
}
}
/**
* Constructs a set of layout params, given width and height specs. In this case, we can set
* the {@code yoga:width} and {@code yoga:height} if we are given them explicitly. If other
* options (such as {@code match_parent} or {@code wrap_content} are given, then the parent
* LayoutParams will store them, and we deal with them during layout. (see
* {@link YogaLayout#createLayout})
*
* @param width the requested width, either a pixel size, {@code WRAP_CONTENT} or
* {@code MATCH_PARENT}.
* @param height the requested height, either a pixel size, {@code WRAP_CONTENT} or
* {@code MATCH_PARENT}.
*/
public LayoutParams(int width, int height) {
super(width, height);
numericAttributes = new SparseArray<>();
stringAttributes = new SparseArray<>();
// Negative values include MATCH_PARENT and WRAP_CONTENT
if (width >= 0) {
numericAttributes.put(R.styleable.yoga_yg_width, (float) width);
}
if (height >= 0) {
numericAttributes.put(R.styleable.yoga_yg_height, (float) height);
}
}
/**
* Constructs a set of layout params, given attributes. Grabs all the {@code yoga:*}
* defined in {@code ALL_YOGA_ATTRIBUTES} and collects the ones that are set in {@code attrs}.
*
* @param context the application environment
* @param attrs the set of attributes from which to extract the yoga specific attributes
*/
public LayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
numericAttributes = new SparseArray<>();
stringAttributes = new SparseArray<>();
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.yoga);
// Negative values include MATCH_PARENT and WRAP_CONTENT
if (width >= 0) {
numericAttributes.put(R.styleable.yoga_yg_width, (float) width);
}
if (height >= 0) {
numericAttributes.put(R.styleable.yoga_yg_height, (float) height);
}
final int attributeCount = a.getIndexCount();
for (int i = 0; i < attributeCount; i++) {
final int attribute = a.getIndex(i);
final TypedValue val = new TypedValue();
a.getValue(attribute, val);
if (val.type == TypedValue.TYPE_DIMENSION) {
numericAttributes.put(
attribute,
(float) a.getDimensionPixelSize(attribute, 0));
} else if (val.type == TypedValue.TYPE_STRING) {
stringAttributes.put(attribute, a.getString(attribute));
} else {
numericAttributes.put(attribute, a.getFloat(attribute, 0));
}
}
a.recycle();
}
}
/**
* Wrapper around measure function for yoga leaves.
*/
public static class ViewMeasureFunction implements YogaMeasureFunction {
/**
* A function to measure leaves of the Yoga tree. Yoga needs some way to know how large
* elements want to be. This function passes that question directly through to the relevant
* {@code View}'s measure function.
*
* @param node The yoga node to measure
* @param width The suggested width from the parent
* @param widthMode The type of suggestion for the width
* @param height The suggested height from the parent
* @param heightMode The type of suggestion for the height
* @return A measurement output ({@code YogaMeasureOutput}) for the node
*/
public long measure(
YogaNodeAPI node,
float width,
YogaMeasureMode widthMode,
float height,
YogaMeasureMode heightMode) {
final View view = (View) node.getData();
if (view == null || view instanceof YogaLayout) {
return YogaMeasureOutput.make(0, 0);
}
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(
(int) width,
viewMeasureSpecFromYogaMeasureMode(widthMode));
final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(
(int) height,
viewMeasureSpecFromYogaMeasureMode(heightMode));
view.measure(widthMeasureSpec, heightMeasureSpec);
return YogaMeasureOutput.make(view.getMeasuredWidth(), view.getMeasuredHeight());
}
private int viewMeasureSpecFromYogaMeasureMode(YogaMeasureMode mode) {
if (mode == YogaMeasureMode.AT_MOST) {
return MeasureSpec.AT_MOST;
} else if (mode == YogaMeasureMode.EXACTLY) {
return MeasureSpec.EXACTLY;
} else {
return MeasureSpec.UNSPECIFIED;
}
}
}
}

View File

@@ -0,0 +1,59 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.yoga.android;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
/**
* A layout inflater factory. This provides our custom {@link YogaViewLayoutFactory#onCreateView}
* to the XML inflation system, allowing us to replace XML tags.
*/
public class YogaViewLayoutFactory implements LayoutInflater.Factory {
private static YogaViewLayoutFactory sYogaViewLayoutFactory;
/**
* Obtains (and initialises if necessary) the singleton {@link YogaViewLayoutFactory}.
*
* @return The singleton instance
*/
public static YogaViewLayoutFactory getInstance() {
if (sYogaViewLayoutFactory == null) {
sYogaViewLayoutFactory = new YogaViewLayoutFactory();
}
return sYogaViewLayoutFactory;
}
YogaViewLayoutFactory() {}
/**
* Hook for inflating from a LayoutInflater. This hook replaces the cumbersome
* {@code com.facebook.etc.YogaLayout} with simply {@code YogaLayout} in your XML and the same
* with {@code VirtualYogaLayout}.
*
* @param name Tag name to be inflated.
* @param context The context the view is being created in.
* @param attrs Inflation attributes as specified in XML file.
*
* @return View Newly created view. Return null for the default behavior.
*/
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
if (YogaLayout.class.getSimpleName().equals(name)) {
return new YogaLayout(context, attrs);
}
if (VirtualYogaLayout.class.getSimpleName().equals(name)) {
return new VirtualYogaLayout(context, attrs);
}
return null;
}
}

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
Copyright (c) 2014-present, Facebook, Inc.
All rights reserved.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree. An additional grant
of patent rights can be found in the PATENTS file in the same directory.
-->
<resources>
<declare-styleable name="yoga">
<attr name="yg_align_content" format="enum">
<enum name="auto" value="0"/>
<enum name="flex_start" value="1"/>
<enum name="center" value="2"/>
<enum name="flex_end" value="3"/>
<enum name="stretch" value="4"/>
<enum name="baseline" value="5"/>
</attr>
<attr name="yg_align_items" format="enum">
<enum name="auto" value="0"/>
<enum name="flex_start" value="1"/>
<enum name="center" value="2"/>
<enum name="flex_end" value="3"/>
<enum name="stretch" value="4"/>
<enum name="baseline" value="5"/>
</attr>
<attr name="yg_align_self" format="enum">
<enum name="auto" value="0"/>
<enum name="flex_start" value="1"/>
<enum name="center" value="2"/>
<enum name="flex_end" value="3"/>
<enum name="stretch" value="4"/>
<enum name="baseline" value="5"/>
</attr>
<attr name="yg_aspect_ratio" format="float"/>
<attr name="yg_border_left" format="dimension"/>
<attr name="yg_border_top" format="dimension"/>
<attr name="yg_border_right" format="dimension"/>
<attr name="yg_border_bottom" format="dimension"/>
<attr name="yg_border_start" format="dimension"/>
<attr name="yg_border_end" format="dimension"/>
<attr name="yg_border_horizontal" format="dimension"/>
<attr name="yg_border_vertical" format="dimension"/>
<attr name="yg_border_all" format="dimension"/>
<attr name="yg_direction" format="enum">
<enum name="inherit" value="0"/>
<enum name="ltr" value="1"/>
<enum name="rtl" value="2"/>
</attr>
<attr name="yg_display" format="enum">
<enum name="flex" value="0"/>
<enum name="none" value="1"/>
</attr>
<attr name="yg_flex" format="float"/>
<attr name="yg_flex_basis" format="float|string"/>
<attr name="yg_flex_direction" format="enum">
<enum name="column" value="0"/>
<enum name="column_reverse" value="1"/>
<enum name="row" value="2"/>
<enum name="row_reverse" value="3"/>
</attr>
<attr name="yg_flex_grow" format="float"/>
<attr name="yg_flex_shrink" format="float"/>
<attr name="yg_height" format="dimension|string"/>
<attr name="yg_justify_content" format="enum">
<enum name="flex_start" value="0"/>
<enum name="center" value="1"/>
<enum name="flex_end" value="2"/>
<enum name="space_between" value="3"/>
<enum name="space_around" value="4"/>
</attr>
<attr name="yg_margin_left" format="dimension|string"/>
<attr name="yg_margin_top" format="dimension|string"/>
<attr name="yg_margin_right" format="dimension|string"/>
<attr name="yg_margin_bottom" format="dimension|string"/>
<attr name="yg_margin_start" format="dimension|string"/>
<attr name="yg_margin_end" format="dimension|string"/>
<attr name="yg_margin_horizontal" format="dimension|string"/>
<attr name="yg_margin_vertical" format="dimension|string"/>
<attr name="yg_margin_all" format="dimension|string"/>
<attr name="yg_max_height" format="dimension|string"/>
<attr name="yg_max_width" format="dimension|string"/>
<attr name="yg_min_height" format="dimension|string"/>
<attr name="yg_min_width" format="dimension|string"/>
<attr name="yg_overflow" format="enum">
<enum name="visible" value="0"/>
<enum name="hidden" value="1"/>
<enum name="scroll" value="2"/>
</attr>
<attr name="yg_padding_left" format="dimension|string"/>
<attr name="yg_padding_top" format="dimension|string"/>
<attr name="yg_padding_right" format="dimension|string"/>
<attr name="yg_padding_bottom" format="dimension|string"/>
<attr name="yg_padding_start" format="dimension|string"/>
<attr name="yg_padding_end" format="dimension|string"/>
<attr name="yg_padding_horizontal" format="dimension|string"/>
<attr name="yg_padding_vertical" format="dimension|string"/>
<attr name="yg_padding_all" format="dimension|string"/>
<attr name="yg_position_left" format="dimension|string"/>
<attr name="yg_position_top" format="dimension|string"/>
<attr name="yg_position_right" format="dimension|string"/>
<attr name="yg_position_bottom" format="dimension|string"/>
<attr name="yg_position_start" format="dimension|string"/>
<attr name="yg_position_end" format="dimension|string"/>
<attr name="yg_position_horizontal" format="dimension|string"/>
<attr name="yg_position_vertical" format="dimension|string"/>
<attr name="yg_position_all" format="dimension|string"/>
<attr name="yg_position_type" format="enum">
<enum name="relative" value="0"/>
<enum name="absolute" value="1"/>
</attr>
<attr name="yg_width" format="dimension|string"/>
<attr name="yg_wrap" format="enum">
<enum name="no_wrap" value="0"/>
<enum name="wrap" value="1"/>
</attr>
</declare-styleable>
</resources>

View File

@@ -5,23 +5,23 @@
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
include_defs('//YOGA_DEFS')
include_defs("//YOGA_DEFS")
cxx_binary(
name = 'benchmark',
srcs = glob(['*.c']),
headers = subdir_glob([('', '*.h')]),
header_namespace = '',
compiler_flags = [
'-fno-omit-frame-pointer',
'-fexceptions',
'-Wall',
'-Werror',
'-O3',
'-std=c11',
],
deps = [
yoga_dep(':yoga'),
],
visibility = ['PUBLIC'],
name = "benchmark",
srcs = glob(["*.c"]),
compiler_flags = [
"-fno-omit-frame-pointer",
"-fexceptions",
"-Wall",
"-Werror",
"-O3",
"-std=c11",
],
header_namespace = "",
headers = subdir_glob([("", "*.h")]),
visibility = ["PUBLIC"],
deps = [
yoga_dep(":yoga"),
],
)

View File

@@ -12,10 +12,10 @@
#include <yoga/Yoga.h>
static YGSize _measure(YGNodeRef node,
float width,
YGMeasureMode widthMode,
float height,
YGMeasureMode heightMode) {
float width,
YGMeasureMode widthMode,
float height,
YGMeasureMode heightMode) {
return (YGSize){
.width = widthMode == YGMeasureModeUndefined ? 10 : width,
.height = heightMode == YGMeasureModeUndefined ? 10 : width,

View File

@@ -17,7 +17,7 @@
#define NUM_REPETITIONS 1000
#define YGBENCHMARKS(BLOCK) \
#define YGBENCHMARKS(BLOCK) \
int main(int argc, char const *argv[]) { \
clock_t __start; \
clock_t __endTimes[NUM_REPETITIONS]; \
@@ -25,7 +25,7 @@
return 0; \
}
#define YGBENCHMARK(NAME, BLOCK) \
#define YGBENCHMARK(NAME, BLOCK) \
__start = clock(); \
for (uint32_t __i = 0; __i < NUM_REPETITIONS; __i++) { \
{ BLOCK } \

32
build.gradle Normal file
View File

@@ -0,0 +1,32 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
classpath 'com.nabilhachicha:android-native-dependencies:0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
flatDir {
dirs "${rootDir}/lib/jsr-305"
dirs "${rootDir}/lib/soloader"
dirs "${rootDir}/lib/appcompat"
dirs "${rootDir}/lib/android-support"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

1
csharp/Android/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
lib/

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{2021459E-8FB1-44A4-89F1-E291769CD2C6}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<RootNamespace>Facebook.Yoga.Android.Tests</RootNamespace>
<AssemblyName>Facebook.Yoga.Android.Tests</AssemblyName>
<TargetFrameworkVersion>v7.1</TargetFrameworkVersion>
<AndroidApplication>True</AndroidApplication>
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
<AndroidResgenClass>Resource</AndroidResgenClass>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<AndroidTlsProvider></AndroidTlsProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidLinkMode>None</AndroidLinkMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidManagedSymbols>true</AndroidManagedSymbols>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="Mono.Android" />
<Reference Include="Xamarin.Android.NUnitLite" />
</ItemGroup>
<ItemGroup>
<Compile Include="MainActivity.cs" />
<Compile Include="Resources\Resource.designer.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Properties\AndroidManifest.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Facebook.Yoga.Android\Facebook.Yoga.Android.csproj">
<Project>{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}</Project>
<Name>Facebook.Yoga.Android</Name>
</ProjectReference>
</ItemGroup>
<Import Project="..\..\tests\Facebook.Yoga\Facebook.Yoga.Shared.Tests.projitems" Label="Shared" Condition="Exists('..\..\tests\Facebook.Yoga\Facebook.Yoga.Shared.Tests.projitems')" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,25 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE-examples file in the root directory of this source tree.
*/
using System.Reflection;
using Android.App;
using Android.OS;
using Xamarin.Android.NUnitLite;
namespace Facebook.Yoga.Android.Tests
{
[Activity(Label = "Facebook.Yoga.Android.Tests", MainLauncher = true)]
public class MainActivity : TestSuiteActivity
{
protected override void OnCreate(Bundle bundle)
{
AddTest(Assembly.GetExecutingAssembly());
base.OnCreate(bundle);
}
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="Facebook.Yoga.Android.Tests">
<uses-sdk
android:minSdkVersion="19" />
<application
android:label="Facebook.Yoga.Android.Tests">
</application>
</manifest>

View File

@@ -0,0 +1,33 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Android.Tests", "Facebook.Yoga.Android.Tests\Facebook.Yoga.Android.Tests.csproj", "{2021459E-8FB1-44A4-89F1-E291769CD2C6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Android", "Facebook.Yoga.Android\Facebook.Yoga.Android.csproj", "{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{4804A8E6-E7B7-4F9E-A446-3DE8E73DB38A}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Facebook.Yoga.Shared", "..\Facebook.Yoga\Facebook.Yoga.Shared.shproj", "{91C42D32-291D-4B72-90B4-551663D60B8B}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Facebook.Yoga.Shared.Tests", "..\tests\Facebook.Yoga\Facebook.Yoga.Shared.Tests.shproj", "{4EDC82D9-A201-4831-8FE0-98F468F8E4AE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|Any CPU.Build.0 = Release|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{91C42D32-291D-4B72-90B4-551663D60B8B} = {4804A8E6-E7B7-4F9E-A446-3DE8E73DB38A}
{4EDC82D9-A201-4831-8FE0-98F468F8E4AE} = {4804A8E6-E7B7-4F9E-A446-3DE8E73DB38A}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildDependsOn>NativeLibraryARMV7;NativeLibraryX86;$(BuildDependsOn)</BuildDependsOn>
</PropertyGroup>
<Target Name="NativeLibraryARMV7" Outputs="$(ProjectDir)/lib/armeabi-v7a/libyoga.so">
<Exec WorkingDirectory="$(ProjectDir)" Command="$(ProjectDir)../../Mac/buck-build.sh //csharp:yoganet#android-armv7,shared" />
<Copy SourceFiles="$(ProjectDir)../../../buck-out/gen/csharp/yoganet#android-armv7,shared/libyoga.so" DestinationFiles="$(ProjectDir)/lib/armeabi-v7a/libyoga.so" SkipUnchangedFiles="true" />
</Target>
<!--
<Target Name="NativeLibraryARM64" Outputs="$(ProjectDir)/lib/arm64-v8a/libyoga.so">
<Exec WorkingDirectory="$(ProjectDir)" Command="$(ProjectDir)../../Mac/buck-build.sh //csharp:yoganet#android-arm64,shared" />
<Copy SourceFiles="$(ProjectDir)../../../buck-out/gen/csharp/yoganet#android-arm64,shared/libyoga.so" DestinationFiles="$(ProjectDir)/lib/arm64-v8/libyoga.so" SkipUnchangedFiles="true" />
</Target>
-->
<Target Name="NativeLibraryX86" Outputs="$(ProjectDir)/lib/x86/libyoga.so">
<Exec WorkingDirectory="$(ProjectDir)" Command="$(ProjectDir)../../Mac/buck-build.sh //csharp:yoganet#android-x86,shared" />
<Copy SourceFiles="$(ProjectDir)../../../buck-out/gen/csharp/yoganet#android-x86,shared/libyoga.so" DestinationFiles="$(ProjectDir)/lib/x86/libyoga.so" SkipUnchangedFiles="true" />
</Target>
</Project>

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<RootNamespace>Facebook.Yoga.Android</RootNamespace>
<AssemblyName>Facebook.Yoga</AssemblyName>
<TargetFrameworkVersion>v7.1</TargetFrameworkVersion>
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
<AndroidResgenClass>Resource</AndroidResgenClass>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
<AndroidTlsProvider></AndroidTlsProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidLinkMode>None</AndroidLinkMode>
<AndroidSupportedAbis>arm64-v8a;armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidManagedSymbols>true</AndroidManagedSymbols>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="Mono.Android" />
</ItemGroup>
<ItemGroup>
<None Include="CustomBuildAction.targets" />
</ItemGroup>
<ItemGroup>
<Folder Include="lib\x86\" />
<Folder Include="lib\armeabi-v7a\" />
</ItemGroup>
<ItemGroup>
<EmbeddedNativeLibrary Include="lib\x86\libyoga.so">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedNativeLibrary>
<EmbeddedNativeLibrary Include="lib\armeabi-v7a\libyoga.so">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedNativeLibrary>
</ItemGroup>
<Import Project="..\..\Facebook.Yoga\Facebook.Yoga.Shared.projitems" Label="Shared" Condition="Exists('..\..\Facebook.Yoga\Facebook.Yoga.Shared.projitems')" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="CustomBuildAction.targets" />
</Project>

View File

@@ -5,41 +5,40 @@
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
include_defs('//YOGA_DEFS')
include_defs("//YOGA_DEFS")
COMPILER_FLAGS = BASE_COMPILER_FLAGS + ['-std=c++11']
COMPILER_FLAGS = BASE_COMPILER_FLAGS + ["-std=c++11"]
csharp_library(
name = 'yogalibnet46',
dll_name = 'Facebook.Yoga.dll',
framework_ver = 'net46',
srcs = glob(['**/*.cs']),
name = "yogalibnet46",
srcs = glob(["**/*.cs"]),
dll_name = "Facebook.Yoga.dll",
framework_ver = "net46",
)
csharp_library(
name = 'yogalibnet45',
dll_name = 'Facebook.Yoga.dll',
framework_ver = 'net45',
srcs = glob(['**/*.cs']),
name = "yogalibnet45",
srcs = glob(["**/*.cs"]),
dll_name = "Facebook.Yoga.dll",
framework_ver = "net45",
)
cxx_library(
name = 'yoganet',
soname = 'libyoga.$(ext)',
srcs = glob(['Yoga/YGInterop.cpp']),
compiler_flags = COMPILER_FLAGS,
link_style = 'static',
link_whole = True,
deps = [yoga_dep(':yoga')],
visibility = ['PUBLIC'],
name = "yoganet",
srcs = glob(["Yoga/YGInterop.cpp"]),
compiler_flags = COMPILER_FLAGS,
link_style = "static",
link_whole = True,
soname = "libyoga.$(ext)",
visibility = ["PUBLIC"],
deps = [yoga_dep(":yoga")],
)
with allow_unsafe_import():
import os
if os.path.isdir('/Applications/Xcode.app'):
if isdir('/Applications/Xcode.app'):
yoganet_ios_srcs = []
for arch in ['iphonesimulator-x86_64', 'iphoneos-arm64', 'iphoneos-armv7']:
for arch in [
'iphonesimulator-x86_64', 'iphonesimulator-i386', 'iphoneos-arm64', 'iphoneos-armv7'
]:
name = 'yoganet-' + arch
yoganet_ios_srcs.append(':' + name)
genrule(
@@ -61,3 +60,15 @@ if os.path.isdir('/Applications/Xcode.app'):
cmd = 'lipo $SRCS -create -output $OUT',
visibility = ['PUBLIC'],
)
yoganet_macosx_target = 'csharp:yoganet#macosx-%s,dynamic'
genrule(
name = 'yoganet-macosx',
srcs = [
yoga_dep(yoganet_macosx_target % 'x86_64'),
yoga_dep(yoganet_macosx_target % 'i386'),
],
out = 'libyoga.dylib',
cmd = 'lipo $SRCS -create -output $OUT',
visibility = ['PUBLIC'],
)

View File

@@ -0,0 +1,130 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{B674A497-DC8E-4286-A889-0C004235AA18}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iOS", "iOS", "{AC14A7DE-A180-46EC-8A88-77F60E73A099}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{09905D88-652D-4A72-8521-6CB1AF347795}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "macOS", "macOS", "{9BDE3670-188E-470F-9B89-CEC0EB042AB5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.iOS", "iOS\Facebook.Yoga.iOS\Facebook.Yoga.iOS.csproj", "{128FB32A-C4A1-4363-BF06-0A36E700B7FA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.iOS.Tests", "iOS\Facebook.Yoga.iOS.Tests\Facebook.Yoga.iOS.Tests.csproj", "{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Facebook.Yoga.Shared", "Facebook.Yoga\Facebook.Yoga.Shared.shproj", "{91C42D32-291D-4B72-90B4-551663D60B8B}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Facebook.Yoga.Shared.Tests", "tests\Facebook.Yoga\Facebook.Yoga.Shared.Tests.shproj", "{4EDC82D9-A201-4831-8FE0-98F468F8E4AE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Android", "Android\Facebook.Yoga.Android\Facebook.Yoga.Android.csproj", "{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Android.Tests", "Android\Facebook.Yoga.Android.Tests\Facebook.Yoga.Android.Tests.csproj", "{2021459E-8FB1-44A4-89F1-E291769CD2C6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuspec", "nuspec", "{2C3685DB-91B9-4207-9446-1C513DB36978}"
ProjectSection(SolutionItems) = preProject
nuget\Facebook.Yoga.dll.config = nuget\Facebook.Yoga.dll.config
nuget\Facebook.Yoga.nuspec = nuget\Facebook.Yoga.nuspec
nuget\Facebook.Yoga.OSX.targets = nuget\Facebook.Yoga.OSX.targets
nuget\Facebook.Yoga.targets = nuget\Facebook.Yoga.targets
nuget\Facebook.Yoga.Universal.targets = nuget\Facebook.Yoga.Universal.targets
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Mac", "Mac\Facebook.Yoga.Mac.csproj", "{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.Yoga.Mac.Tests", "Mac\Facebook.Yoga.Mac.Tests\Facebook.Yoga.Mac.Tests.csproj", "{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Debug|iPhoneSimulator = Debug|iPhoneSimulator
Release|iPhone = Release|iPhone
Release|iPhoneSimulator = Release|iPhoneSimulator
Debug|iPhone = Debug|iPhone
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|Any CPU.Build.0 = Release|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|iPhone.ActiveCfg = Release|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|iPhone.Build.0 = Release|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{128FB32A-C4A1-4363-BF06-0A36E700B7FA}.Debug|iPhone.Build.0 = Debug|Any CPU
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|Any CPU.ActiveCfg = Release|iPhone
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|Any CPU.Build.0 = Release|iPhone
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|iPhone.ActiveCfg = Release|iPhone
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|iPhone.Build.0 = Release|iPhone
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|iPhone.ActiveCfg = Debug|iPhone
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71}.Debug|iPhone.Build.0 = Debug|iPhone
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|Any CPU.Build.0 = Release|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|iPhone.ActiveCfg = Release|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|iPhone.Build.0 = Release|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363}.Debug|iPhone.Build.0 = Debug|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|Any CPU.Build.0 = Release|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|iPhone.ActiveCfg = Release|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|iPhone.Build.0 = Release|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{2021459E-8FB1-44A4-89F1-E291769CD2C6}.Debug|iPhone.Build.0 = Debug|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|Any CPU.Build.0 = Release|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|iPhone.ActiveCfg = Release|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|iPhone.Build.0 = Release|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71}.Debug|iPhone.Build.0 = Debug|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|Any CPU.Build.0 = Release|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|iPhone.ActiveCfg = Release|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|iPhone.Build.0 = Release|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77}.Debug|iPhone.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{128FB32A-C4A1-4363-BF06-0A36E700B7FA} = {AC14A7DE-A180-46EC-8A88-77F60E73A099}
{FCF0BE59-AE56-4D4F-8524-94532B2DFC71} = {AC14A7DE-A180-46EC-8A88-77F60E73A099}
{91C42D32-291D-4B72-90B4-551663D60B8B} = {09905D88-652D-4A72-8521-6CB1AF347795}
{4EDC82D9-A201-4831-8FE0-98F468F8E4AE} = {09905D88-652D-4A72-8521-6CB1AF347795}
{EDF7CF8B-5640-4E1D-A2C7-E4BC8BE44363} = {B674A497-DC8E-4286-A889-0C004235AA18}
{2021459E-8FB1-44A4-89F1-E291769CD2C6} = {B674A497-DC8E-4286-A889-0C004235AA18}
{19A1C7D7-C9CC-476A-B604-DF6A3DE1BA71} = {9BDE3670-188E-470F-9B89-CEC0EB042AB5}
{9FCB6149-DFA8-4EAA-B4DB-2E91A5D8FF77} = {9BDE3670-188E-470F-9B89-CEC0EB042AB5}
EndGlobalSection
EndGlobal

View File

@@ -1,46 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Yoga", "Yoga\Yoga.vcxproj", "{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Facebook.Yoga", "Facebook.Yoga\Facebook.Yoga.xproj", "{75BB7605-E54B-4EDE-8F5A-FF1F24464236}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Debug|Any CPU.ActiveCfg = Debug|Win32
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Debug|x64.ActiveCfg = Debug|x64
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Debug|x64.Build.0 = Debug|x64
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Debug|x86.ActiveCfg = Debug|Win32
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Debug|x86.Build.0 = Debug|Win32
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Release|Any CPU.ActiveCfg = Release|Win32
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Release|x64.ActiveCfg = Release|x64
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Release|x64.Build.0 = Release|x64
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Release|x86.ActiveCfg = Release|Win32
{0446C86B-F47B-4C46-B673-C7AE0CFF35D5}.Release|x86.Build.0 = Release|Win32
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|x64.ActiveCfg = Debug|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|x64.Build.0 = Debug|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|x86.ActiveCfg = Debug|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Debug|x86.Build.0 = Debug|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|Any CPU.Build.0 = Release|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|x64.ActiveCfg = Release|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|x64.Build.0 = Release|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|x86.ActiveCfg = Release|Any CPU
{75BB7605-E54B-4EDE-8F5A-FF1F24464236}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,13 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.Yoga
{
public delegate float BaselineFunction(YogaNode node, float width, float height);
}

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<SharedGUID>91c42d32-291d-4b72-90b4-551663d60b8b</SharedGUID>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<Import_RootNamespace>Facebook.Yoga.Shared</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)BaselineFunction.cs" />
<Compile Include="$(MSBuildThisFileDirectory)MeasureFunction.cs" />
<Compile Include="$(MSBuildThisFileDirectory)MeasureOutput.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Native.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaAlign.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaBaselineFunc.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaConstants.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaDimension.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaDirection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaDisplay.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaEdge.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaExperimentalFeature.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaFlexDirection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaJustify.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaLogger.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaLogLevel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaMeasureFunc.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaMeasureMode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaNode.Spacing.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaNode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaOverflow.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaPositionType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaPrintOptions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaSize.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaUnit.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaValue.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaValueExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaWrap.cs" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>91c42d32-291d-4b72-90b4-551663d60b8b</ProjectGuid>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
<PropertyGroup />
<Import Project="Facebook.Yoga.Shared.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
</Project>

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>75bb7605-e54b-4ede-8f5a-ff1f24464236</ProjectGuid>
<RootNamespace>Facebook.Yoga</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -1,4 +1,4 @@
/**
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
@@ -12,6 +12,12 @@ using System.Runtime.InteropServices;
namespace Facebook.Yoga
{
#if WINDOWS_UWP_ARM
using YogaValueType = IntPtr;
#else
using YogaValueType = YogaValue;
#endif
internal static class Native
{
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
@@ -22,6 +28,10 @@ namespace Facebook.Yoga
internal class YGNodeHandle : SafeHandle
{
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
private GCHandle _managed;
#endif
private YGNodeHandle() : base(IntPtr.Zero, true)
{
}
@@ -36,258 +46,399 @@ namespace Facebook.Yoga
protected override bool ReleaseHandle()
{
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
if (_managed.IsAllocated)
{
_managed.Free();
}
#endif
Native.YGNodeFree(this.handle);
GC.KeepAlive(this);
return true;
}
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
public void SetContext(YogaNode node)
{
if (!_managed.IsAllocated)
{
_managed = GCHandle.Alloc(node, GCHandleType.Weak);
Native.YGNodeSetContext(this.handle, GCHandle.ToIntPtr(_managed));
}
}
public static YogaNode GetManaged(IntPtr ygNodePtr)
{
var node =
GCHandle.FromIntPtr(Native.YGNodeGetContext(ygNodePtr)).Target as YogaNode;
if (node == null)
{
throw new InvalidOperationException("YogaNode is already deallocated");
}
return node;
}
#endif
}
internal class YGConfigHandle : SafeHandle
{
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
private GCHandle _managed;
#endif
private YGConfigHandle() : base(IntPtr.Zero, true)
{
}
public override bool IsInvalid
{
get
{
return this.handle == IntPtr.Zero;
}
}
protected override bool ReleaseHandle()
{
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
if (_managed.IsAllocated)
{
_managed.Free();
}
#endif
Native.YGConfigFree(this.handle);
GC.KeepAlive(this);
return true;
}
}
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGInteropSetLogger(
[MarshalAs(UnmanagedType.FunctionPtr)] YogaLogger.Func func);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YGNodeHandle YGNodeNew();
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YGNodeHandle YGNodeNewWithConfig(YGConfigHandle config);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeFree(IntPtr node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeReset(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YGConfigHandle YGConfigNew();
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGConfigFree(IntPtr node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int YGNodeGetInstanceCount();
[DllImport(DllName)]
public static extern void YGSetExperimentalFeatureEnabled(
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGConfigSetExperimentalFeatureEnabled(
YGConfigHandle config,
YogaExperimentalFeature feature,
bool enabled);
[DllImport(DllName)]
public static extern bool YGIsExperimentalFeatureEnabled(
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern bool YGConfigIsExperimentalFeatureEnabled(
YGConfigHandle config,
YogaExperimentalFeature feature);
[DllImport(DllName)]
public static extern void YGNodeInsertChild(YGNodeHandle node, YGNodeHandle child, uint index);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeInsertChild(
YGNodeHandle node,
YGNodeHandle child,
uint index);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeRemoveChild(YGNodeHandle node, YGNodeHandle child);
[DllImport(DllName)]
public static extern void YGNodeCalculateLayout(YGNodeHandle node,
float availableWidth,
float availableHeight,
YogaDirection parentDirection);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeCalculateLayout(
YGNodeHandle node,
float availableWidth,
float availableHeight,
YogaDirection parentDirection);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeMarkDirty(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool YGNodeIsDirty(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodePrint(YGNodeHandle node, YogaPrintOptions options);
[DllImport(DllName)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool YGValueIsUndefined(float value);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeCopyStyle(YGNodeHandle dstNode, YGNodeHandle srcNode);
#region YG_NODE_PROPERTY
#region YG_NODE_PROPERTY
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeSetMeasureFunc(
YGNodeHandle node,
[MarshalAs(UnmanagedType.FunctionPtr)] YogaMeasureFunc measureFunc);
[DllImport(DllName)]
[return: MarshalAs(UnmanagedType.FunctionPtr)]
public static extern YogaMeasureFunc YGNodeGetMeasureFunc(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeSetBaselineFunc(
YGNodeHandle node,
[MarshalAs(UnmanagedType.FunctionPtr)] YogaBaselineFunc baselineFunc);
[DllImport(DllName)]
public static extern void YGNodeSetHasNewLayout(YGNodeHandle node, [MarshalAs(UnmanagedType.I1)] bool hasNewLayout);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeSetHasNewLayout(
YGNodeHandle node,
[MarshalAs(UnmanagedType.I1)] bool hasNewLayout);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool YGNodeGetHasNewLayout(YGNodeHandle node);
#endregion
#endregion
#region YG_NODE_STYLE_PROPERTY
#region YG_NODE_STYLE_PROPERTY
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetDirection(YGNodeHandle node, YogaDirection direction);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaDirection YGNodeStyleGetDirection(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetFlexDirection(YGNodeHandle node, YogaFlexDirection flexDirection);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaFlexDirection YGNodeStyleGetFlexDirection(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetJustifyContent(YGNodeHandle node, YogaJustify justifyContent);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaJustify YGNodeStyleGetJustifyContent(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetAlignContent(YGNodeHandle node, YogaAlign alignContent);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaAlign YGNodeStyleGetAlignContent(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetAlignItems(YGNodeHandle node, YogaAlign alignItems);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaAlign YGNodeStyleGetAlignItems(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetAlignSelf(YGNodeHandle node, YogaAlign alignSelf);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaAlign YGNodeStyleGetAlignSelf(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetPositionType(YGNodeHandle node, YogaPositionType positionType);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaPositionType YGNodeStyleGetPositionType(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetFlexWrap(YGNodeHandle node, YogaWrap flexWrap);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaWrap YGNodeStyleGetFlexWrap(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetOverflow(YGNodeHandle node, YogaOverflow flexWrap);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaOverflow YGNodeStyleGetOverflow(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetDisplay(YGNodeHandle node, YogaDisplay display);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaDisplay YGNodeStyleGetDisplay(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetFlex(YGNodeHandle node, float flex);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetFlexGrow(YGNodeHandle node, float flexGrow);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeStyleGetFlexGrow(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetFlexShrink(YGNodeHandle node, float flexShrink);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeStyleGetFlexShrink(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetFlexBasis(YGNodeHandle node, float flexBasis);
[DllImport(DllName)]
public static extern float YGNodeStyleGetFlexBasis(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetFlexBasisPercent(YGNodeHandle node, float flexBasis);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetFlexBasisAuto(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValueType YGNodeStyleGetFlexBasis(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetWidth(YGNodeHandle node, float width);
[DllImport(DllName)]
public static extern float YGNodeStyleGetWidth(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetWidthPercent(YGNodeHandle node, float width);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetWidthAuto(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValueType YGNodeStyleGetWidth(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetHeight(YGNodeHandle node, float height);
[DllImport(DllName)]
public static extern float YGNodeStyleGetHeight(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetHeightPercent(YGNodeHandle node, float height);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetHeightAuto(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValueType YGNodeStyleGetHeight(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMinWidth(YGNodeHandle node, float minWidth);
[DllImport(DllName)]
public static extern float YGNodeStyleGetMinWidth(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMinWidthPercent(YGNodeHandle node, float minWidth);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValueType YGNodeStyleGetMinWidth(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMinHeight(YGNodeHandle node, float minHeight);
[DllImport(DllName)]
public static extern float YGNodeStyleGetMinHeight(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMinHeightPercent(YGNodeHandle node, float minHeight);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValueType YGNodeStyleGetMinHeight(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMaxWidth(YGNodeHandle node, float maxWidth);
[DllImport(DllName)]
public static extern float YGNodeStyleGetMaxWidth(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMaxWidthPercent(YGNodeHandle node, float maxWidth);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValueType YGNodeStyleGetMaxWidth(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMaxHeight(YGNodeHandle node, float maxHeight);
[DllImport(DllName)]
public static extern float YGNodeStyleGetMaxHeight(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMaxHeightPercent(YGNodeHandle node, float maxHeight);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValueType YGNodeStyleGetMaxHeight(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetAspectRatio(YGNodeHandle node, float aspectRatio);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeStyleGetAspectRatio(YGNodeHandle node);
#endregion
#endregion
#region YG_NODE_STYLE_EDGE_PROPERTY
#region YG_NODE_STYLE_EDGE_PROPERTY
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetPosition(YGNodeHandle node, YogaEdge edge, float position);
[DllImport(DllName)]
public static extern float YGNodeStyleGetPosition(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetPositionPercent(YGNodeHandle node, YogaEdge edge, float position);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValueType YGNodeStyleGetPosition(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMargin(YGNodeHandle node, YogaEdge edge, float margin);
[DllImport(DllName)]
public static extern float YGNodeStyleGetMargin(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMarginPercent(YGNodeHandle node, YogaEdge edge, float margin);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMarginAuto(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValueType YGNodeStyleGetMargin(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetPadding(YGNodeHandle node, YogaEdge edge, float padding);
[DllImport(DllName)]
public static extern float YGNodeStyleGetPadding(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetPaddingPercent(YGNodeHandle node, YogaEdge edge, float padding);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValueType YGNodeStyleGetPadding(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetBorder(YGNodeHandle node, YogaEdge edge, float border);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeStyleGetBorder(YGNodeHandle node, YogaEdge edge);
#endregion
#endregion
#region YG_NODE_LAYOUT_PROPERTY
#region YG_NODE_LAYOUT_PROPERTY
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeLayoutGetLeft(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeLayoutGetTop(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeLayoutGetRight(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeLayoutGetBottom(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeLayoutGetWidth(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeLayoutGetHeight(YGNodeHandle node);
[DllImport(DllName)]
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeLayoutGetMargin(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeLayoutGetPadding(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaDirection YGNodeLayoutGetDirection(YGNodeHandle node);
#endregion
#endregion
#region IOS
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr YGNodeGetContext(IntPtr node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeSetContext(IntPtr node, IntPtr managed);
#endif
#endregion
}
}

View File

@@ -1,31 +0,0 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.Yoga
{
public class Spacing
{
public float? Top;
public float? Bottom;
public float? Left;
public float? Right;
public Spacing(
float? top = null,
float? bottom = null,
float? left = null,
float? right = null)
{
Top = top;
Bottom = bottom;
Left = left;
Right = right;
}
}
}

View File

@@ -16,5 +16,8 @@ namespace Facebook.Yoga
Center,
FlexEnd,
Stretch,
Baseline,
SpaceBetween,
SpaceAround,
}
}

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
using System;
using System.Runtime.InteropServices;
namespace Facebook.Yoga
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float YogaBaselineFunc(IntPtr node, float width, float height);
}

View File

@@ -17,5 +17,10 @@ namespace Facebook.Yoga
{
return float.IsNaN(value);
}
public static bool IsUndefined(YogaValue value)
{
return value.Unit == YogaUnit.Undefined;
}
}
}

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.Yoga
{
public enum YogaDisplay
{
Flex,
None,
}
}

View File

@@ -13,5 +13,6 @@ namespace Facebook.Yoga
{
Rounding,
WebFlexBasis,
MinFlexFix,
}
}

View File

@@ -10,6 +10,10 @@
using System;
using System.Runtime.InteropServices;
#if __IOS__
using ObjCRuntime;
#endif
namespace Facebook.Yoga
{
internal static class YogaLogger
@@ -18,25 +22,30 @@ namespace Facebook.Yoga
public delegate void Func(YogaLogLevel level, string message);
private static bool _initialized;
private static Func _managedLogger = null;
private static Func _managedLogger = LoggerInternal;
public static Func Logger = null;
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
[MonoPInvokeCallback(typeof(Func))]
#endif
public static void LoggerInternal(YogaLogLevel level, string message)
{
if (Logger != null)
{
Logger(level, message);
}
if (level == YogaLogLevel.Error)
{
throw new InvalidOperationException(message);
}
}
public static void Initialize()
{
if (!_initialized)
{
_managedLogger = (level, message) => {
if (Logger != null)
{
Logger(level, message);
}
if (level == YogaLogLevel.Error)
{
throw new InvalidOperationException(message);
}
};
Native.YGInteropSetLogger(_managedLogger);
_initialized = true;
}

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