Compare commits
908 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
88994129ae | ||
|
888892885e | ||
|
de79f2a1d4 | ||
|
6368416178 | ||
|
a935a222b5 | ||
|
7c4da0a341 | ||
|
b047af25ca | ||
|
2abd9dd91b | ||
|
afadc5cf6b | ||
|
8823cc357a | ||
|
8b8d9a05b7 | ||
|
15668aceb6 | ||
|
e25fe994b3 | ||
|
47abe1c482 | ||
|
95169c3150 | ||
|
7331de78bd | ||
|
05f36a835a | ||
|
dcd9438488 | ||
|
d38db1292c | ||
|
4463fe0856 | ||
|
2156de5fb5 | ||
|
b1c749075d | ||
|
367a93de88 | ||
|
2643b96589 | ||
|
016a10df26 | ||
|
cbcf07f08a | ||
|
59bcac3289 | ||
|
bd90192df9 | ||
|
e7fcf1ee65 | ||
|
f86c74ce7e | ||
|
d5ad51bccc | ||
|
0bdf36f5d1 | ||
|
1b9053bc5d | ||
|
446101a168 | ||
|
f0324035bf | ||
|
a2f94cbf9a | ||
|
d21fa68033 | ||
|
5a6d84abc9 | ||
|
61ae484316 | ||
|
42657017bd | ||
|
9b9a344934 | ||
|
5f92ba49a7 | ||
|
2e564c21cd | ||
|
ca7d4d1633 | ||
|
3645f43cea | ||
|
9378a7a439 | ||
|
d3e02b15fa | ||
|
80d527814e | ||
|
5121fef5d8 | ||
|
0d026bd1a0 | ||
|
719fa3cca3 | ||
|
307cf09434 | ||
|
8691cdaed6 | ||
|
4a6b1e19b8 | ||
|
31ce3ab866 | ||
|
0846439c8e | ||
|
000d1436b4 | ||
|
1bc97a5e48 | ||
|
68f7001ed4 | ||
|
59446294b3 | ||
|
460370b7d3 | ||
|
cbea5d44b8 | ||
|
b4b009c2d8 | ||
|
74dd627495 | ||
|
58f0cca7c7 | ||
|
3de3575ac4 | ||
|
390fade8c0 | ||
|
96dfe068ee | ||
|
e0eb37fce0 | ||
|
79355ab72d | ||
|
5a9f29debb | ||
|
8b8932811e | ||
|
604a9a98a9 | ||
|
71321f763a | ||
|
7fa0816d81 | ||
|
4840495d3f | ||
|
866bf101b2 | ||
|
3467308874 | ||
|
ef2c693b05 | ||
|
efac22a508 | ||
|
4b97375524 | ||
|
ab9d06abf5 | ||
|
5ee32fbefc | ||
|
899664dddd | ||
|
b66642cb86 | ||
|
b9ae948ce9 | ||
|
138521ccc2 | ||
|
5514722ce2 | ||
|
56e133ab4c | ||
|
f6415889ca | ||
|
885b4cbdfb | ||
|
8461aeaef0 | ||
|
3df41aefdb | ||
|
8bc89651d6 | ||
|
c5f2444048 | ||
|
130a9a2aa2 | ||
|
dd97fcc968 | ||
|
4f51871fa8 | ||
|
e96d14395c | ||
|
852db1d885 | ||
|
3f79439718 | ||
|
96d93f2982 | ||
|
236bcc1a39 | ||
|
4b5ae211da | ||
|
aaa018bbea | ||
|
6bdd39d0ed | ||
|
da678ef971 | ||
|
e9078374c9 | ||
|
f23a669ed0 | ||
|
9ddda3c630 | ||
|
8ab01fde6e | ||
|
440c719190 | ||
|
e522b2dee4 | ||
|
b26e637c81 | ||
|
6b7f6980f9 | ||
|
4248fd9d4c | ||
|
5a65261a55 | ||
|
5719132f58 | ||
|
10b316f315 | ||
|
b6498987fa | ||
|
9680ae98a6 | ||
|
59755d2874 | ||
|
64c37767c2 | ||
|
50ec35575f | ||
|
ed3b54b603 | ||
|
ed5c5a799f | ||
|
d19da9e528 | ||
|
0962c5220c | ||
|
b9972cee6e | ||
|
98c1c180af | ||
|
6f6e0ce339 | ||
|
bdae838516 | ||
|
6d8ee77791 | ||
|
9725d5b21b | ||
|
8e48edaa0b | ||
|
89394a2dd6 | ||
|
02a2309b2a | ||
|
8f181c7259 | ||
|
339c5574b8 | ||
|
8d5bbecd3d | ||
|
dd12907632 | ||
|
7d7d9a7ef0 | ||
|
63570613d3 | ||
|
4e2011c381 | ||
|
7a60399b2b | ||
|
a0b3586fb3 | ||
|
a2ef8978cd | ||
|
d02f4a94de | ||
|
b7890fa2a8 | ||
|
1e4d0abc66 | ||
|
eb2aeb3adb | ||
|
fad2ee1a64 | ||
|
ba9bd4eae3 | ||
|
e12b78f99b | ||
|
5d1cee2bf0 | ||
|
5c711a7076 | ||
|
838ef47847 | ||
|
786ccddd7b | ||
|
b747286c1d | ||
|
bb3c2b2498 | ||
|
36e732aabd | ||
|
d6517ae288 | ||
|
93d327acfb | ||
|
01c6c79efb | ||
|
357ca78f9f | ||
|
6e46eec58f | ||
|
554d8cdf76 | ||
|
328ec7dc4d | ||
|
2e66f8d828 | ||
|
e224a29d1c | ||
|
238d7ba98f | ||
|
d6ba8326d1 | ||
|
f7df575746 | ||
|
2b52c73d70 | ||
|
7a45fb39bf | ||
|
1080cf22e3 | ||
|
1d09227374 | ||
|
85031baaf2 | ||
|
7f71cac3b0 | ||
|
48a8f883ba | ||
|
6132a59772 | ||
|
8309cfc976 | ||
|
abc9fdb37c | ||
|
b872751d68 | ||
|
8368338c93 | ||
|
45c44d293c | ||
|
b4a889553c | ||
|
78cdf3cadc | ||
|
be78bfbd8c | ||
|
c5d4485db3 | ||
|
71f1d99494 | ||
|
0e99980206 | ||
|
292bfed102 | ||
|
78d6988461 | ||
|
3499e2e0ef | ||
|
b1821ab4cd | ||
|
006f6460a9 | ||
|
db5bc092aa | ||
|
9fe20fd2fc | ||
|
7b87ded288 | ||
|
eaaf0fdfe2 | ||
|
4caed8feb5 | ||
|
4be229059c | ||
|
389f2fd85d | ||
|
f95e3b49e9 | ||
|
f172d5d41c | ||
|
7be9fd1a79 | ||
|
5e1796505d | ||
|
51a4601e18 | ||
|
0bc4d23e2e | ||
|
4c47dcbd0f | ||
|
c1a9f6120a | ||
|
1b32c4f054 | ||
|
896cfbdfde | ||
|
910aa77c01 | ||
|
2562c029b1 | ||
|
0b1780a081 | ||
|
e9e2ae28e0 | ||
|
4ed3dd4b82 | ||
|
a7f430a5ef | ||
|
89ba4f282d | ||
|
b6231ee0ed | ||
|
e384002878 | ||
|
9ceed4b601 | ||
|
765bb85d1e | ||
|
6548dddec3 | ||
|
966f5ece4a | ||
|
ede2888326 | ||
|
2eda444bbf | ||
|
7c4319181b | ||
|
f4d29e6f11 | ||
|
77ea79490f | ||
|
46c96ee2cb | ||
|
a67c555320 | ||
|
cdb1ee21a0 | ||
|
2ce219ef42 | ||
|
c5f826de83 | ||
|
526ca42d04 | ||
|
b47f0ce41a | ||
|
eb7cb11ffd | ||
|
f9df990177 | ||
|
684dccb7b9 | ||
|
6c51eb4f72 | ||
|
ca485dfb50 | ||
|
50e3714b21 | ||
|
c52c7cdd1e | ||
|
11200f3d75 | ||
|
5dbe3c128b | ||
|
3564ccf6e4 | ||
|
e1c19cecad | ||
|
8e4f3a3084 | ||
|
9b8323ff38 | ||
|
5b7adda620 | ||
|
ba2a3b8c91 | ||
|
eb15939c23 | ||
|
b9fa60fd74 | ||
|
d397aa04d7 | ||
|
adb1b11055 | ||
|
2e234473ca | ||
|
6b08db68bb | ||
|
9550126f76 | ||
|
bad262b961 | ||
|
3c6c10075a | ||
|
6a77a6939e | ||
|
b725a4a140 | ||
|
2b714a5b5d | ||
|
572546088f | ||
|
5b109578d3 | ||
|
77b720f9a5 | ||
|
de954eb9cc | ||
|
3e322e60e4 | ||
|
a3642541d0 | ||
|
bb139d3f91 | ||
|
08743a42e2 | ||
|
cb6e76973d | ||
|
4b760fa9bc | ||
|
5730be093e | ||
|
d85e2ee9c3 | ||
|
fe433b012f | ||
|
5e3ffb39a2 | ||
|
f0edefdbb7 | ||
|
17901ea5c2 | ||
|
187fc54596 | ||
|
c951ad7c7b | ||
|
9785975f77 | ||
|
79281049f2 | ||
|
7d2b84aab6 | ||
|
cda328fa7e | ||
|
5d7b75a47a | ||
|
ae86824636 | ||
|
0dde40ce0b | ||
|
369c9ad12a | ||
|
cfb9eeca20 | ||
|
3dfb68887d | ||
|
d567885070 | ||
|
877c275a13 | ||
|
8aadae8ce4 | ||
|
2232d7603a | ||
|
b3f8851bc2 | ||
|
47ad3f63cf | ||
|
c75adb0671 | ||
|
178b8f5f64 | ||
|
a874992e7c | ||
|
31fc287d35 | ||
|
892913a69d | ||
|
99026e42a9 | ||
|
3a82d2b1a8 | ||
|
b28292e454 | ||
|
2ff18bc948 | ||
|
d0bee487e0 | ||
|
419e29c5a6 | ||
|
295d111f0e | ||
|
da5eb2db67 | ||
|
3408e4d4fa | ||
|
6d7eca8e42 | ||
|
5726a71b62 | ||
|
f73b5057ac | ||
|
51051aad7f | ||
|
91d3c08248 | ||
|
52f2cf319a | ||
|
bbdb62e654 | ||
|
e024943c4b | ||
|
7f44ec512e | ||
|
a2b6ddb7b1 | ||
|
bdc37b0797 | ||
|
82aaebfea2 | ||
|
48d82224ee | ||
|
100afcfdb0 | ||
|
b3436d5eba | ||
|
c5371aca64 | ||
|
269619a419 | ||
|
9b3104577c | ||
|
a1697d2307 | ||
|
056b75858c | ||
|
c84ed90272 | ||
|
b21dd9891a | ||
|
bba81781af | ||
|
0c74a72fac | ||
|
1822bc5eaf | ||
|
01ffe10c2f | ||
|
7f99a547f5 | ||
|
0e5651fb80 | ||
|
0ca44f3001 | ||
|
3f85763797 | ||
|
b318c4c5c9 | ||
|
ae9703712a | ||
|
d617ab6662 | ||
|
4c3eebd3e5 | ||
|
10061af491 | ||
|
91621641e6 | ||
|
35c6931ade | ||
|
44622912a2 | ||
|
aac40cf89b | ||
|
d4b20f5793 | ||
|
89df2d9475 | ||
|
79fa6f8d58 | ||
|
69242938f7 | ||
|
1b66b5d941 | ||
|
fb30f7ddcb | ||
|
747c2a4208 | ||
|
43fda26275 | ||
|
b1222bf83e | ||
|
3ec41b656f | ||
|
740ef6cd9e | ||
|
8c5cbf698b | ||
|
5f2cf6623f | ||
|
4b7efb73d7 | ||
|
a6b7e34187 | ||
|
e50308e823 | ||
|
b6a13ce43a | ||
|
96a87a811d | ||
|
025ee03cb1 | ||
|
c06ee92251 | ||
|
3aca5965dc | ||
|
cac77e5ffa | ||
|
49f1d7b5f6 | ||
|
82e44dbf04 | ||
|
9b501dd9eb | ||
|
8ba663f6f4 | ||
|
8f35484262 | ||
|
1e3143656d | ||
|
699b1f5012 | ||
|
9c877a621e | ||
|
a3144150e0 | ||
|
c830083df3 | ||
|
9eb03b1bcd | ||
|
7e3136c347 | ||
|
c3de8016c0 | ||
|
af45863f8e | ||
|
08d7d1673e | ||
|
e7c56ccd1e | ||
|
de8cab8e60 | ||
|
9e0f751464 | ||
|
951a429ac5 | ||
|
e43bb9da19 | ||
|
b08bd572ef | ||
|
402ee11273 | ||
|
6e38a26f32 | ||
|
d66239bea8 | ||
|
7eb8df2777 | ||
|
75473fd924 | ||
|
c94ade8ffd | ||
|
61afbd43c9 | ||
|
64f6ea37bd | ||
|
dc0609d153 | ||
|
bd46344a4e | ||
|
7199902316 | ||
|
250873abf2 | ||
|
1e775ecb83 | ||
|
9718c517d9 | ||
|
afc215aa66 | ||
|
5df8157863 | ||
|
802fe6bb29 | ||
|
27d2ad198e | ||
|
63be3ff84c | ||
|
66045bd13d | ||
|
f5f8105b57 | ||
|
4f92ae46ef | ||
|
80f8aa3c7e | ||
|
42778f687b | ||
|
7b27a58b97 | ||
|
a40ba9d350 | ||
|
9ecdff14fa | ||
|
288adc49c9 | ||
|
b8c2428b31 | ||
|
92bfcbafc0 | ||
|
130b5beca2 | ||
|
adb2e0fdd6 | ||
|
0a04bd7f2f | ||
|
9d6af5b314 | ||
|
6efb4b90d4 | ||
|
5806f1728c | ||
|
a9dd527748 | ||
|
db3d20b7b7 | ||
|
acd4e01aaf | ||
|
b217f23ba5 | ||
|
76875af207 | ||
|
f2ba14c309 | ||
|
a65b79a944 | ||
|
681b580fd8 | ||
|
b985b6c377 | ||
|
92eda21e78 | ||
|
0cfdb50477 | ||
|
1eb9a5edd9 | ||
|
383b881748 | ||
|
47543c8fba | ||
|
dc6ed89bfa | ||
|
348dd368b5 | ||
|
40eeefd4f7 | ||
|
47892c17ce | ||
|
f2a369fb73 | ||
|
61dc10ef66 | ||
|
7d01f4d8b1 | ||
|
c7a5e1e290 | ||
|
fbd332dee8 | ||
|
dbf6a12134 | ||
|
dbc47ae383 | ||
|
f22cfd52e0 | ||
|
2a10337344 | ||
|
836eaa62df | ||
|
a01c7adcfb | ||
|
5133faa1ad | ||
|
6a8c2960ad | ||
|
0c98e89fdb | ||
|
5f78181911 | ||
|
03dd1d23fa | ||
|
91683be798 | ||
|
109cb1a562 | ||
|
ad1240e276 | ||
|
2e468d9c8c | ||
|
6caa94b779 | ||
|
429a7eeee3 | ||
|
dec1172f38 | ||
|
afaafb4126 | ||
|
e566fcca08 | ||
|
c7f7ba250c | ||
|
7e3be21811 | ||
|
5e39f1a57c | ||
|
5aa0f44a9b | ||
|
55c767ba7f | ||
|
5502a97f7f | ||
|
8ab1d81917 | ||
|
942543f6a5 | ||
|
a69545a6ae | ||
|
0b13a0c168 | ||
|
d8341ca3b0 | ||
|
34ac314101 | ||
|
02c00f2711 | ||
|
15231c3304 | ||
|
d98e5aef97 | ||
|
5b0dfa471f | ||
|
26481a6553 | ||
|
64e08aa98b | ||
|
0c3168f150 | ||
|
40861c699e | ||
|
d8fee24778 | ||
|
5c617a5947 | ||
|
ff0a3f39d9 | ||
|
bfb4dabf0c | ||
|
58d14ee557 | ||
|
c5182c4bf5 | ||
|
132b016bae | ||
|
4785e95a0c | ||
|
be94a5ef8d | ||
|
208b70a93c | ||
|
6c3155ae3b | ||
|
32f071c2ad | ||
|
fdd1dbe3a9 | ||
|
1ca5bb694d | ||
|
b4cfaa916c | ||
|
fc6c85996e | ||
|
969f055f47 | ||
|
58328d01ef | ||
|
d90914f3dc | ||
|
3a0a86788e | ||
|
a77aa9a41e | ||
|
7217471427 | ||
|
bcc36cc1b2 | ||
|
16052085d0 | ||
|
c20f2864ab | ||
|
4185a44393 | ||
|
c79c5e3c9d | ||
|
35a9f33abb | ||
|
32f128640b | ||
|
18d19af7ec | ||
|
2ee2dd439f | ||
|
5edfb679e7 | ||
|
f45059e1e6 | ||
|
c9384762ee | ||
|
7ea50439ce | ||
|
154e67adbc | ||
|
570a193b7e | ||
|
79e294c927 | ||
|
5d75c7c4c8 | ||
|
7c688cea68 | ||
|
7640cd667f | ||
|
24e2fc95dd | ||
|
ce3f99939f | ||
|
11bc97b16c | ||
|
4804bcd594 | ||
|
ca2c607f90 | ||
|
6c67684fa6 | ||
|
835b2bbae8 | ||
|
47edd2586c | ||
|
ca483cae00 | ||
|
a20bde8444 | ||
|
ac885626b3 | ||
|
976ecc6816 | ||
|
d2f22283bb | ||
|
56b10fc35b | ||
|
5a3ceffba1 | ||
|
b378a685a4 | ||
|
fa50f048f1 | ||
|
f68b50bb4b | ||
|
aad1c3055c | ||
|
cd1dbc3f0f | ||
|
bf4ff0769d | ||
|
a141ebfb50 | ||
|
2fb01daf70 | ||
|
e9e1e084da | ||
|
629e401deb | ||
|
f4c2b6ae63 | ||
|
4487862227 | ||
|
927eca6604 | ||
|
f2612192c5 | ||
|
49bccf47fa | ||
|
fa54167a20 | ||
|
50feb21cb3 | ||
|
52ce5828c9 | ||
|
9cdaedfcb5 | ||
|
adad054cad | ||
|
b2b0c7ee37 | ||
|
488a7c1fe0 | ||
|
85c2e406e4 | ||
|
dcf57d2f7e | ||
|
3fefe9fc49 | ||
|
626a05fb6f | ||
|
ffcd2cfc8a | ||
|
181101c92d | ||
|
3db6804202 | ||
|
3fb135829d | ||
|
2c91e1e7d2 | ||
|
c3982b6c1e | ||
|
ae33c6c19c | ||
|
bcd68b997f | ||
|
fcfa1b9f01 | ||
|
d9a0822517 | ||
|
097e99b699 | ||
|
ff7bec703b | ||
|
c7ab004922 | ||
|
91230ae177 | ||
|
40eba60cf5 | ||
|
fb4cfed20d | ||
|
d3a9a84ac4 | ||
|
accad5366f | ||
|
8eca67e257 | ||
|
40e1bf6ce3 | ||
|
7b89a1dd48 | ||
|
203577724e | ||
|
e3dbef7cbd | ||
|
0ee3303791 | ||
|
83fddd8af6 | ||
|
77c05b5ff6 | ||
|
7c324f058c | ||
|
3db38f2a80 | ||
|
f6b17183c5 | ||
|
8f9d7e243e | ||
|
fde4db9383 | ||
|
3178e3bf15 | ||
|
cdfd05c742 | ||
|
76f6a54327 | ||
|
c91e4b3566 | ||
|
e24561bcef | ||
|
363e941867 | ||
|
3fb2c1888c | ||
|
aa5b296ac7 | ||
|
f2b5d0fef7 | ||
|
0684795a89 | ||
|
2ffc23f400 | ||
|
dc4d16401f | ||
|
849de89a58 | ||
|
f8a2903d02 | ||
|
60977de242 | ||
|
cb612bcfbe | ||
|
6be1c2cdb4 | ||
|
034ab0b3b1 | ||
|
8c50347f3c | ||
|
9f76fb6980 | ||
|
8b0ff0a25c | ||
|
8891ea1a7a | ||
|
ede2ad94bc | ||
|
eacf3cdbb4 | ||
|
3569a13b74 | ||
|
b2a96ec744 | ||
|
a505adb2b7 | ||
|
906b6e52f8 | ||
|
3292337754 | ||
|
eb4af86e3c | ||
|
1b3e971549 | ||
|
4615eee2d8 | ||
|
7c57245943 | ||
|
0d100ad7e9 | ||
|
0235789863 | ||
|
c080a46571 | ||
|
5f050cb590 | ||
|
25f14a1917 | ||
|
e9927377b5 | ||
|
3ea76f8a9b | ||
|
8a45ed9671 | ||
|
1520749351 | ||
|
f66f52d1ba | ||
|
49e18738c3 | ||
|
586b57009a | ||
|
5112564f08 | ||
|
34726a9926 | ||
|
5884ab7b76 | ||
|
60db018ce4 | ||
|
6b002bad3d | ||
|
5b173c1b61 | ||
|
bc2fb5c7ab | ||
|
ebdf82f491 | ||
|
36f6fa9861 | ||
|
91a34bb875 | ||
|
d342fb1879 | ||
|
b283572453 | ||
|
62a74a5ef9 | ||
|
a14aeb27bb | ||
|
249d010dad | ||
|
9b13fdeae4 | ||
|
794b6b35ce | ||
|
dcff4d3db2 | ||
|
b94466e502 | ||
|
11052053d8 | ||
|
6ab3984bba | ||
|
136e0c7e52 | ||
|
7e2ef926ea | ||
|
061981fb23 | ||
|
3d6fb2f2e5 | ||
|
a8e6123d47 | ||
|
406c8a2117 | ||
|
0445962bd4 | ||
|
09f0c2d8ce | ||
|
8dea884a69 | ||
|
57898762a2 | ||
|
01bf8d7b6c | ||
|
af8d55c08e | ||
|
53398b42c6 | ||
|
1bf142e048 | ||
|
0405c4f77d | ||
|
61595763b0 | ||
|
f6ecc8da7b | ||
|
32792a0de5 | ||
|
c3d60b55bd | ||
|
17be6718ee | ||
|
abf912b729 | ||
|
5bc0197c78 | ||
|
62f47190fb | ||
|
a706f4c97c | ||
|
feb365a77b | ||
|
b2a4e67fee | ||
|
e7d2792009 | ||
|
0fde1424f0 | ||
|
29fd447f0c | ||
|
7047d96087 | ||
|
6336e641f4 | ||
|
ecabe757a2 | ||
|
37c48257ae | ||
|
8668e43f6d | ||
|
785713c9c0 | ||
|
b523402eda | ||
|
3790635af1 | ||
|
b940fadb7e | ||
|
3ef2970032 | ||
|
4372aa16d3 | ||
|
3346f9511a | ||
|
1cd7363bea | ||
|
17e3dca9f9 | ||
|
533f560ce0 | ||
|
6a60d4893e | ||
|
51dd082682 | ||
|
47d8d9d22b | ||
|
d6d4dcb141 | ||
|
37ec1774a7 | ||
|
3ad4d7dd6e | ||
|
e596091fa2 | ||
|
4f5c7ed6af | ||
|
60ffa1953b | ||
|
5519a73087 | ||
|
67717a7872 | ||
|
4522d4b8aa | ||
|
d7ca339c27 | ||
|
6b39165801 | ||
|
78ade6cfb5 | ||
|
3f68b4f76b | ||
|
521aab5fcc | ||
|
42492596b3 | ||
|
b24e728666 | ||
|
4fe0b810e1 | ||
|
8deed174f5 | ||
|
2184547094 | ||
|
8eda4dc040 | ||
|
4d4db92a46 | ||
|
ea8b7e0c91 | ||
|
6928957096 | ||
|
b680b726d1 | ||
|
fbd692c449 | ||
|
2199a7908d | ||
|
59704f1508 | ||
|
20536923d6 | ||
|
bba7289537 | ||
|
04d1ccc085 | ||
|
a7e7c5eb52 | ||
|
9d2839f8ca | ||
|
1146013e9e | ||
|
8a91c0a0e5 | ||
|
a1c75454e9 | ||
|
ad3963daa6 | ||
|
a66339d63c | ||
|
d0bdd4dc91 | ||
|
d24078be31 | ||
|
f251648726 | ||
|
b587ecb30f | ||
|
a580712b2f | ||
|
ce5d52b54e | ||
|
55fe6f0bc9 | ||
|
abf142ea3f | ||
|
ae9f89b5d1 | ||
|
058761e16e | ||
|
ad8c6225fd | ||
|
1cbadf5f54 | ||
|
e7021715b8 | ||
|
0d2749a3fd | ||
|
76fbd628e1 | ||
|
15309d2bdd | ||
|
4f6924a0c1 | ||
|
063f65d065 | ||
|
adf8691093 | ||
|
6a7ad2125d | ||
|
247aa26d3e | ||
|
3c9f620c77 | ||
|
e0e2a61dfc | ||
|
168ae4099d | ||
|
6ceb4af2d4 | ||
|
240c2dd657 | ||
|
a5b94ebd0c | ||
|
5037c2f365 | ||
|
ef05404bee | ||
|
3db493665e | ||
|
737f1cc67c | ||
|
b5c2b09780 | ||
|
46817a38c3 | ||
|
52f3471405 | ||
|
e567502750 | ||
|
c1cdc1de58 | ||
|
f2c41f366f | ||
|
56d06e27cf | ||
|
93e327f4a5 | ||
|
687668a4b3 | ||
|
cfeac79130 | ||
|
4227e36ca5 | ||
|
be1c9f249e | ||
|
511a129a7e | ||
|
d62ca8c518 | ||
|
30413265c7 | ||
|
bd5d8a77c9 | ||
|
326ae15532 | ||
|
9afb65da34 | ||
|
fe7643c84a | ||
|
6daad3ae66 | ||
|
44590b8907 | ||
|
4400b52aab | ||
|
c217553cf8 | ||
|
6ad5003149 | ||
|
7c77b0e48c | ||
|
7b36118df4 | ||
|
7f0dbe5356 | ||
|
b87fc217df | ||
|
625dc4bf44 | ||
|
34736a4929 | ||
|
4f37cde043 | ||
|
7df60376ff | ||
|
7fa4adb0d9 | ||
|
abb91ae77b | ||
|
a4b1ac83f4 | ||
|
8775cdc13f | ||
|
db732ce9fa | ||
|
7c09244c39 | ||
|
2cc2a5f2ff | ||
|
e4b50f2a8d | ||
|
a2a84532ff | ||
|
d391323129 | ||
|
ab28ecf31b | ||
|
a4bab68802 | ||
|
e3cfacf0cb | ||
|
8d74e01f41 | ||
|
5404bb13d4 | ||
|
be8773fee0 | ||
|
0bcec80dfe | ||
|
2c8c2bffda | ||
|
d70f289e73 | ||
|
498a5980e8 | ||
|
8021c5d968 | ||
|
c536ab214d | ||
|
adb81e2a1e | ||
|
c4a3e12add | ||
|
a3d7d72421 | ||
|
47266b9ae8 | ||
|
e39f13a8ea | ||
|
c04604dbc0 | ||
|
1782646723 | ||
|
78e64e3d5b | ||
|
0acb620159 | ||
|
9982295e10 | ||
|
8ed71b2777 | ||
|
969b3709db | ||
|
e2a7938b26 | ||
|
70a4221b9e | ||
|
8d320ceac2 | ||
|
c169a98be6 | ||
|
6d48307c8d | ||
|
e539ecc9aa | ||
|
bf5eeaf61e | ||
|
a36faf89e3 | ||
|
29c44e281c | ||
|
1877a97898 | ||
|
bf6602ebff | ||
|
6bcf0e3a50 | ||
|
d0aeabb8f0 | ||
|
956df20c64 | ||
|
7108454455 | ||
|
663a93912b | ||
|
a85bd4ad2a | ||
|
6f462a72bf | ||
|
352f592767 | ||
|
f2080e520f | ||
|
cd78291de5 | ||
|
ab595d1875 | ||
|
597544e30a | ||
|
9f59a13836 | ||
|
12017e49bd | ||
|
abad796c44 | ||
|
92137273a2 | ||
|
f1ab289022 | ||
|
a302b76d59 | ||
|
4717594e93 | ||
|
df0f76bba5 | ||
|
e43c9f66ff | ||
|
0df58d8aa2 | ||
|
ff1a0e1eb8 | ||
|
ed765fe508 | ||
|
1b5eb7da5e | ||
|
071f576db9 | ||
|
3d10ba5f72 | ||
|
85b8386ba1 | ||
|
7ec3607446 | ||
|
835bb1cd9c | ||
|
9d35dce63e | ||
|
74fb205083 | ||
|
ba0bb10366 | ||
|
0296511f2c | ||
|
04fe81f88f | ||
|
98bbc15435 | ||
|
25b206ac53 | ||
|
88a4e44fd4 | ||
|
642ea07d6f | ||
|
e85c5ce39d | ||
|
cf753af247 | ||
|
12efe604bb |
@@ -1,2 +1,10 @@
|
|||||||
[cxx]
|
[cxx]
|
||||||
gtest_dep = //lib/gtest:gtest
|
gtest_dep = //lib/gtest:gtest
|
||||||
|
[android]
|
||||||
|
target = android-25
|
||||||
|
build_tools_version = 26.0.2
|
||||||
|
[ndk]
|
||||||
|
ndk_version = 15.2.4203891
|
||||||
|
compiler = clang
|
||||||
|
app_platform = android-21
|
||||||
|
cpu_abis = arm64, armv7, x86, x86_64
|
||||||
|
56
.clang-format
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
Language: Cpp
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: false
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakBeforeBinaryOperators: false
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 80
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 2000
|
||||||
|
PointerAlignment: Left
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: false
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
Standard: Cpp11
|
||||||
|
UseTab: Never
|
1
.clang-format-ignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
^lib/.*
|
11
.editorconfig
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
17
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Report
|
||||||
|
|
||||||
|
- [ ] I have searched [existing issues](https://github.com/facebook/yoga/issues) and this is not a duplicate
|
||||||
|
|
||||||
|
# Issues and Steps to Reproduce
|
||||||
|
***Replaces this with steps to repro your issue.***
|
||||||
|
|
||||||
|
# Expected Behavior
|
||||||
|
***Describe what you expected would happen.***
|
||||||
|
|
||||||
|
# Actual Behavior
|
||||||
|
***Describe what actually happened.***
|
||||||
|
|
||||||
|
# Link to Code
|
||||||
|
***If you have some code that maintainers can clone/test for themselves, bugs can be resolved much faster. Please paste a link here.***
|
||||||
|
|
||||||
|
***When applicable, use this [fiddle](https://jsfiddle.net/emilsjolander/jckmwztt/) to post a web repro.***
|
57
.gitignore
vendored
@@ -5,6 +5,63 @@
|
|||||||
/.buckconfig.local
|
/.buckconfig.local
|
||||||
/.buckd
|
/.buckd
|
||||||
/gentest/test.html
|
/gentest/test.html
|
||||||
|
.buckversion
|
||||||
|
|
||||||
|
# Jekyll
|
||||||
|
/.sass-cache/
|
||||||
|
/_site/
|
||||||
|
|
||||||
# Visual studio code
|
# Visual studio code
|
||||||
.vscode
|
.vscode
|
||||||
|
*.pdb
|
||||||
|
*.tlog
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.log
|
||||||
|
*.orig
|
||||||
|
|
||||||
|
# Xcode
|
||||||
|
## Build generated
|
||||||
|
build/
|
||||||
|
DerivedData/
|
||||||
|
|
||||||
|
## Various settings
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
## Other
|
||||||
|
*.moved-aside
|
||||||
|
*.xcuserstate
|
||||||
|
|
||||||
|
## Obj-C/Swift specific
|
||||||
|
*.hmap
|
||||||
|
*.ipa
|
||||||
|
*.dSYM.zip
|
||||||
|
*.dSYM
|
||||||
|
|
||||||
|
# CocoaPods
|
||||||
|
#
|
||||||
|
# We recommend against adding the Pods directory to your .gitignore. However
|
||||||
|
# you should judge for yourself, the pros and cons are mentioned at:
|
||||||
|
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||||
|
#
|
||||||
|
Pods/
|
||||||
|
|
||||||
|
# Carthage
|
||||||
|
#
|
||||||
|
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||||
|
# Carthage/Checkouts
|
||||||
|
|
||||||
|
Carthage/Build
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.gradle
|
||||||
|
# NDK/CMake
|
||||||
|
.externalNativeBuild
|
||||||
|
10
.hgignore
@@ -1,10 +0,0 @@
|
|||||||
.DS_STORE
|
|
||||||
|
|
||||||
/buck-cache/
|
|
||||||
/buck-out/
|
|
||||||
/.buckconfig.local
|
|
||||||
/.buckd
|
|
||||||
/gentest/test.html
|
|
||||||
|
|
||||||
# Visual studio code
|
|
||||||
.vscode
|
|
1
.swift-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.0
|
96
.travis.yml
@@ -1,30 +1,76 @@
|
|||||||
# Copyright (c) 2014-present, Facebook, Inc.
|
language: java
|
||||||
# All rights reserved.
|
os: linux
|
||||||
#
|
addons:
|
||||||
# This source code is licensed under the BSD-style license found in the
|
apt:
|
||||||
# LICENSE file in the root directory of this source tree. An additional grant
|
sources:
|
||||||
# of patent rights can be found in the PATENTS file in the same directory.
|
- llvm-toolchain-trusty-6.0
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- clang-6.0
|
||||||
|
|
||||||
os: osx
|
env:
|
||||||
osx_image: xcode7.3
|
- TARGET: website
|
||||||
language: cpp
|
- TARGET: android
|
||||||
compiler: clang
|
|
||||||
|
install:
|
||||||
|
- cd website
|
||||||
|
- yarn --ignore-scripts
|
||||||
|
- cd ..
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/buck
|
||||||
|
- $HOME/.gradle
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- brew update
|
- |
|
||||||
- brew tap facebook/fb
|
if [[ -n "$encrypted_d27e803291ff_iv" ]]; then
|
||||||
- brew install buck
|
openssl aes-256-cbc -K $encrypted_d27e803291ff_key -iv $encrypted_d27e803291ff_iv -in scripts/setup-keys.enc -d >> gradle.properties;
|
||||||
- brew cask install java
|
fi
|
||||||
- brew outdated xctool || brew upgrade xctool
|
# Android
|
||||||
- brew install mono
|
- |
|
||||||
- export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
|
if [[ $TARGET = "android" ]]; then
|
||||||
- export PATH=$JAVA_HOME/bin:$PATH
|
pushd $HOME
|
||||||
|
git clone --depth 1 https://github.com/facebook/buck.git
|
||||||
|
cd buck
|
||||||
|
ant
|
||||||
|
popd
|
||||||
|
export PATH=$PATH:$HOME/buck/bin/
|
||||||
|
buck --version
|
||||||
|
export TERMINAL=dumb
|
||||||
|
source scripts/android-setup.sh && installAndroidSDK
|
||||||
|
export ANDROID_SDK=$ANDROID_HOME
|
||||||
|
export ANDROID_NDK_REPOSITORY=$HOME/android-ndk
|
||||||
|
export ANDROID_NDK_HOME=$ANDROID_NDK_REPOSITORY/android-ndk-r15c
|
||||||
|
fi
|
||||||
|
# Website
|
||||||
|
- |
|
||||||
|
if [[ $TARGET = "website" ]]; then
|
||||||
|
nvm install 8
|
||||||
|
nvm use 8
|
||||||
|
fi
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- buck test //:yoga
|
- |
|
||||||
- buck test //java:java
|
if [[ $TARGET = "android" ]]; then
|
||||||
- buck test //YogaKit:YogaKitTests --config cxx.default_platform=iphonesimulator-x86_64 --config cxx.cflags=-DTRAVIS_CI
|
./gradlew testDebugUnit && scripts/publish-snapshot.sh
|
||||||
- sh csharp/tests/Facebook.Yoga/test_macos.sh
|
fi
|
||||||
- buck run //benchmark:benchmark
|
- |
|
||||||
- git checkout HEAD^
|
if [[ $TARGET = "website" ]]; then
|
||||||
- buck run //benchmark:benchmark
|
pushd website
|
||||||
|
yarn build
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
provider: pages
|
||||||
|
skip-cleanup: true
|
||||||
|
github-token: $GITHUB_TOKEN
|
||||||
|
fqdn: yogalayout.com
|
||||||
|
local-dir: website/public
|
||||||
|
email: yogabot@fb.com
|
||||||
|
name: Yoga-bot
|
||||||
|
keep-history: true
|
||||||
|
on:
|
||||||
|
branch: master
|
||||||
|
condition: $TARGET = website
|
||||||
|
63
BUCK
@@ -1,50 +1,45 @@
|
|||||||
# Copyright (c) 2014-present, Facebook, Inc.
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
# All rights reserved.
|
|
||||||
#
|
#
|
||||||
# This source code is licensed under the BSD-style license found in the
|
# This source code is licensed under the MIT license found in the
|
||||||
# LICENSE file in the root directory of this source tree. An additional grant
|
# LICENSE file in the root directory of this source tree.
|
||||||
# of patent rights can be found in the PATENTS file in the same directory.
|
load("//tools/build_defs/oss:yoga_defs.bzl", "BASE_COMPILER_FLAGS", "GTEST_TARGET", "LIBRARY_COMPILER_FLAGS", "subdir_glob", "yoga_cxx_library", "yoga_cxx_test", "yoga_dep")
|
||||||
|
|
||||||
include_defs('//YOGA_DEFS')
|
|
||||||
|
|
||||||
BASE_COMPILER_FLAGS = [
|
|
||||||
'-fno-omit-frame-pointer',
|
|
||||||
'-fexceptions',
|
|
||||||
'-Wall',
|
|
||||||
'-Werror',
|
|
||||||
'-O3',
|
|
||||||
]
|
|
||||||
|
|
||||||
GMOCK_OVERRIDE_FLAGS = [
|
GMOCK_OVERRIDE_FLAGS = [
|
||||||
# gmock does not mark mocked methods as override, ignore the warnings in tests
|
# gmock does not mark mocked methods as override, ignore the warnings in tests
|
||||||
'-Wno-inconsistent-missing-override',
|
"-Wno-inconsistent-missing-override",
|
||||||
]
|
]
|
||||||
|
|
||||||
COMPILER_FLAGS = BASE_COMPILER_FLAGS + ['-std=c11', '-fPIC']
|
COMPILER_FLAGS = LIBRARY_COMPILER_FLAGS + [
|
||||||
TEST_COMPILER_FLAGS = BASE_COMPILER_FLAGS + GMOCK_OVERRIDE_FLAGS + ['-std=c++11']
|
"-std=c++1y",
|
||||||
|
]
|
||||||
|
|
||||||
cxx_library(
|
TEST_COMPILER_FLAGS = BASE_COMPILER_FLAGS + GMOCK_OVERRIDE_FLAGS + [
|
||||||
name = 'yoga',
|
"-std=c++1y",
|
||||||
soname = 'libyogacore.$(ext)',
|
]
|
||||||
srcs = glob(['yoga/*.c']),
|
|
||||||
tests=[':YogaTests'],
|
yoga_cxx_library(
|
||||||
exported_headers = subdir_glob([('', 'yoga/*.h')]),
|
name = "yoga",
|
||||||
header_namespace = '',
|
srcs = glob(["yoga/*.cpp"]),
|
||||||
|
header_namespace = "",
|
||||||
|
exported_headers = subdir_glob([("", "yoga/*.h")]),
|
||||||
compiler_flags = COMPILER_FLAGS,
|
compiler_flags = COMPILER_FLAGS,
|
||||||
deps = [] if THIS_IS_FBOBJC else [
|
soname = "libyogacore.$(ext)",
|
||||||
yoga_dep('lib/fb:ndklog'),
|
tests = [":YogaTests"],
|
||||||
|
visibility = ["PUBLIC"],
|
||||||
|
deps = [
|
||||||
|
yoga_dep("lib/fb:ndklog"),
|
||||||
],
|
],
|
||||||
visibility = ['PUBLIC'],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cxx_test(
|
yoga_cxx_test(
|
||||||
name = 'YogaTests',
|
name = "YogaTests",
|
||||||
contacts = ['emilsj@fb.com'],
|
srcs = glob(["tests/*.cpp"]),
|
||||||
srcs = glob(['tests/*.cpp']),
|
headers = subdir_glob([("", "yoga/**/*.h")]),
|
||||||
compiler_flags = TEST_COMPILER_FLAGS,
|
compiler_flags = TEST_COMPILER_FLAGS,
|
||||||
|
contacts = ["emilsj@fb.com"],
|
||||||
|
visibility = ["PUBLIC"],
|
||||||
deps = [
|
deps = [
|
||||||
':yoga',
|
":yoga",
|
||||||
GTEST_TARGET,
|
GTEST_TARGET,
|
||||||
],
|
],
|
||||||
visibility = ['PUBLIC'],
|
|
||||||
)
|
)
|
||||||
|
15
CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.4.1)
|
||||||
|
|
||||||
|
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||||
|
|
||||||
|
file(GLOB yogacore_SRC yoga/*.cpp)
|
||||||
|
add_library(yogacore STATIC ${yogacore_SRC})
|
||||||
|
|
||||||
|
target_link_libraries(yogacore android log)
|
3
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Code of Conduct
|
||||||
|
|
||||||
|
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct/) so that you can understand what actions will and will not be tolerated.
|
@@ -2,6 +2,10 @@
|
|||||||
We want to make contributing to this project as easy and transparent as
|
We want to make contributing to this project as easy and transparent as
|
||||||
possible.
|
possible.
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct/) so that you can understand what actions will and will not be tolerated.
|
||||||
|
|
||||||
## Pull Requests
|
## Pull Requests
|
||||||
We actively welcome your pull requests.
|
We actively welcome your pull requests.
|
||||||
1. Fork the repo and create your branch from `master`.
|
1. Fork the repo and create your branch from `master`.
|
||||||
@@ -25,9 +29,6 @@ Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
|
|||||||
disclosure of security bugs. In those cases, please go through the process
|
disclosure of security bugs. In those cases, please go through the process
|
||||||
outlined on that page and do not file a public issue.
|
outlined on that page and do not file a public issue.
|
||||||
|
|
||||||
## Coding Style
|
|
||||||
* format.sh
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
By contributing to yoga, you agree that your contributions will be licensed
|
By contributing to yoga, you agree that your contributions will be licensed
|
||||||
under its BSD license.
|
under its MIT license.
|
43
LICENSE
@@ -1,30 +1,21 @@
|
|||||||
BSD License
|
MIT License
|
||||||
|
|
||||||
For yoga software
|
Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
|
||||||
Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
The above copyright notice and this permission notice shall be included in all
|
||||||
are permitted provided that the following conditions are met:
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
list of conditions and the following disclaimer.
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
this list of conditions and the following disclaimer in the documentation
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
and/or other materials provided with the distribution.
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
* Neither the name Facebook nor the names of its contributors may be used to
|
|
||||||
endorse or promote products derived from this software without specific
|
|
||||||
prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
33
PATENTS
@@ -1,33 +0,0 @@
|
|||||||
Additional Grant of Patent Rights Version 2
|
|
||||||
|
|
||||||
"Software" means the yoga software distributed by Facebook, Inc.
|
|
||||||
|
|
||||||
Facebook, Inc. (“Facebook”) hereby grants to each recipient of the Software
|
|
||||||
(“you”) a perpetual, worldwide, royalty-free, non-exclusive, irrevocable
|
|
||||||
(subject to the termination provision below) license under any Necessary
|
|
||||||
Claims, to make, have made, use, sell, offer to sell, import, and otherwise
|
|
||||||
transfer the Software. For avoidance of doubt, no license is granted under
|
|
||||||
Facebook's rights in any patent claims that are infringed by (i) modifications
|
|
||||||
to the Software made by you or any third party or (ii) the Software in
|
|
||||||
combination with any software or other technology.
|
|
||||||
|
|
||||||
The license granted hereunder will terminate, automatically and without notice,
|
|
||||||
if you (or any of your subsidiaries, corporate affiliates or agents) initiate
|
|
||||||
directly or indirectly, or take a direct financial interest in, any Patent
|
|
||||||
Assertion: (i) against Facebook or any of its subsidiaries or corporate
|
|
||||||
affiliates, (ii) against any party if such Patent Assertion arises in whole or
|
|
||||||
in part from any software, technology, product or service of Facebook or any of
|
|
||||||
its subsidiaries or corporate affiliates, or (iii) against any party relating
|
|
||||||
to the Software. Notwithstanding the foregoing, if Facebook or any of its
|
|
||||||
subsidiaries or corporate affiliates files a lawsuit alleging patent
|
|
||||||
infringement against you in the first instance, and you respond by filing a
|
|
||||||
patent infringement counterclaim in that lawsuit against that party that is
|
|
||||||
unrelated to the Software, the license granted hereunder will not terminate
|
|
||||||
under section (i) of this paragraph due to such counterclaim.
|
|
||||||
|
|
||||||
A "Necessary Claim" is a claim of a patent owned by Facebook that is
|
|
||||||
necessarily infringed by the Software standing alone.
|
|
||||||
|
|
||||||
A "Patent Assertion" is any lawsuit or other action alleging direct, indirect,
|
|
||||||
or contributory infringement or inducement to infringe any patent, including a
|
|
||||||
cross-claim or counterclaim.
|
|
32
README.md
@@ -1,12 +1,14 @@
|
|||||||
# Yoga [](https://travis-ci.org/facebook/yoga)
|
# Yoga [](http://cocoapods.org/pods/YogaKit) [](https://www.npmjs.com/package/yoga-layout) [](https://bintray.com/facebook/maven/com.facebook.yoga%3Ayoga/_latestVersion) [](https://www.nuget.org/packages/Facebook.Yoga)
|
||||||
|
|
||||||
## Building
|
## 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.
|
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.
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
For testing we rely on [gtest](https://github.com/google/googletest) as a submodule. After cloning Yoga run `git submodule init` followed by `git submodule update`.
|
||||||
|
|
||||||
For any changes you make you should ensure that all the tests are passing. In case you make any fixes or additions to the library please also add tests for that change to ensure we don't break anything in the future. Tests are located in the `tests` directory. Run the tests by executing `buck test //:yoga`.
|
For any changes you make you should ensure that all the tests are passing. In case you make any fixes or additions to the library please also add tests for that change to ensure we don't break anything in the future. Tests are located in the `tests` directory. Run the tests by executing `buck test //:yoga`.
|
||||||
|
|
||||||
Instead of manually writing a test which ensures parity with web implementations of Flexbox you can run `gentest/gentest.rb` to generated a test for you. You can write html which you want to verify in Yoga, in `gentest/fixtures` folder, such as the following.
|
Instead of manually writing a test which ensures parity with web implementations of Flexbox you can run `gentest/gentest.rb` to generate a test for you. You can write html which you want to verify in Yoga, in `gentest/fixtures` folder, such as the following.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div id="my_test" style="width: 100px; height: 100px; align-items: center;">
|
<div id="my_test" style="width: 100px; height: 100px; align-items: center;">
|
||||||
@@ -21,8 +23,26 @@ You may need to install the latest watir-webdriver gem (`gem install watir-webdr
|
|||||||
### .NET
|
### .NET
|
||||||
.NET testing is not integrated in buck yet, you might need to set up .NET testing environment. We have a script which to launch C# test on macOS, `csharp/tests/Facebook.Yoga/test_macos.sh`.
|
.NET testing is not integrated in buck yet, you might need to set up .NET testing environment. We have a script which to launch C# test on macOS, `csharp/tests/Facebook.Yoga/test_macos.sh`.
|
||||||
|
|
||||||
## Code style
|
|
||||||
For the main C implementation of Yoga clang-format is used to ensure a consistent code style. Please run `bash format.sh` before submitting a pull request. For other languages just try to follow the current code style.
|
|
||||||
|
|
||||||
## Benchmarks
|
## Benchmarks
|
||||||
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.
|
||||||
|
|
||||||
|
### JavaScript
|
||||||
|
Installing through NPM
|
||||||
|
```sh
|
||||||
|
npm install yoga-layout
|
||||||
|
```
|
||||||
|
By default this will install the library and try to build for all platforms (node, browser asm, and standalone webpack). You may receive errors if you do not have the required platform development tools already installed. To preset the platform you'd like to build for you can set a .npmrc property first.
|
||||||
|
```sh
|
||||||
|
npm config set yoga-layout:platform standalone
|
||||||
|
```
|
||||||
|
This will now only run the standalone webpack build upon install.
|
||||||
|
|
||||||
|
## Build Platforms
|
||||||
|
|
||||||
|
| name | description |
|
||||||
|
|----------------|-------------------------------------------------|
|
||||||
|
| all (default) | Builds all of these platforms. |
|
||||||
|
| browser | Builds asm js browser version. |
|
||||||
|
| node | Builds node js version. |
|
||||||
|
| standalone | Runs webpack. |
|
||||||
|
| none | Does nothing. You can use the prepackaged libs. |
|
||||||
|
27
YOGA_DEFS
@@ -1,27 +0,0 @@
|
|||||||
|
|
||||||
YOGA_ROOT = '//...'
|
|
||||||
INFER_ANNOTATIONS_TARGET = '//lib/infer-annotations:infer-annotations'
|
|
||||||
JSR_305_TARGET = '//lib/jsr-305:jsr-305'
|
|
||||||
JUNIT_TARGET = '//lib/junit:junit'
|
|
||||||
PROGRUARD_ANNOTATIONS_TARGET = '//java/com/facebook/proguard/annotations:annotations'
|
|
||||||
SOLOADER_TARGET = '//lib/soloader:soloader'
|
|
||||||
GTEST_TARGET = '//lib/gtest:gtest'
|
|
||||||
JNI_TARGET = '//lib/jni:jni'
|
|
||||||
FBJNI_TARGET = '//lib/fb:fbjni'
|
|
||||||
|
|
||||||
THIS_IS_FBOBJC = False
|
|
||||||
|
|
||||||
CXX_LIBRARY_WHITELIST = [
|
|
||||||
'//:yoga',
|
|
||||||
'//lib/fb:fbjni',
|
|
||||||
'//java:jni',
|
|
||||||
]
|
|
||||||
|
|
||||||
def yoga_dep(dep):
|
|
||||||
return '//' + dep
|
|
||||||
|
|
||||||
class allow_unsafe_import:
|
|
||||||
def __enter__(self):
|
|
||||||
pass
|
|
||||||
def __exit__(self, type, value, traceback):
|
|
||||||
pass
|
|
39
Yoga.podspec
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
# file in the root directory of this source tree.
|
||||||
|
#
|
||||||
|
Pod::Spec.new do |spec|
|
||||||
|
spec.name = 'Yoga'
|
||||||
|
spec.version = '1.12.0-pre.1'
|
||||||
|
spec.license = { :type => 'MIT', :file => "LICENSE" }
|
||||||
|
spec.homepage = 'https://yogalayout.com/'
|
||||||
|
spec.documentation_url = 'https://yogalayout.com/docs'
|
||||||
|
|
||||||
|
spec.summary = 'Yoga is a cross-platform layout engine which implements Flexbox.'
|
||||||
|
spec.description = 'Yoga is a cross-platform layout engine enabling maximum collaboration within your team by implementing an API many designers are familiar with, and opening it up to developers across different platforms.'
|
||||||
|
|
||||||
|
spec.authors = 'Facebook'
|
||||||
|
spec.source = {
|
||||||
|
:git => 'https://github.com/facebook/yoga.git',
|
||||||
|
:tag => spec.version.to_s,
|
||||||
|
}
|
||||||
|
spec.platforms = { :ios => "4.3", :osx => "10.7", :tvos => "10.0", :watchos => "2.0" }
|
||||||
|
spec.module_name = 'yoga'
|
||||||
|
spec.requires_arc = false
|
||||||
|
spec.pod_target_xcconfig = {
|
||||||
|
'DEFINES_MODULE' => 'YES'
|
||||||
|
}
|
||||||
|
spec.compiler_flags = [
|
||||||
|
'-fno-omit-frame-pointer',
|
||||||
|
'-fexceptions',
|
||||||
|
'-Wall',
|
||||||
|
'-Werror',
|
||||||
|
'-std=c++1y',
|
||||||
|
'-fPIC'
|
||||||
|
]
|
||||||
|
spec.source_files = 'yoga/**/*.{c,h,cpp}'
|
||||||
|
spec.public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGValue}.h'
|
||||||
|
|
||||||
|
end
|
36
YogaKit.podspec
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
# file in the root directory of this source tree.
|
||||||
|
#
|
||||||
|
podspec = Pod::Spec.new do |spec|
|
||||||
|
spec.name = 'YogaKit'
|
||||||
|
spec.version = '1.12.0'
|
||||||
|
spec.license = { :type => 'MIT', :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 => spec.version.to_s,
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.platform = :ios
|
||||||
|
spec.ios.deployment_target = '8.0'
|
||||||
|
spec.ios.frameworks = 'UIKit'
|
||||||
|
|
||||||
|
spec.dependency 'Yoga', '~> 1.9'
|
||||||
|
spec.source_files = 'YogaKit/Source/*.{h,m,swift}'
|
||||||
|
spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h'
|
||||||
|
spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h'
|
||||||
|
spec.swift_version = '3.0'
|
||||||
|
end
|
||||||
|
|
||||||
|
# See https://github.com/facebook/yoga/pull/366
|
||||||
|
podspec.attributes_hash["readme"] = "YogaKit/README.md"
|
||||||
|
podspec
|
1
YogaKit/.swift-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.0.2
|
86
YogaKit/BUCK
@@ -1,58 +1,64 @@
|
|||||||
# Copyright (c) 2014-present, Facebook, Inc.
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
# All rights reserved.
|
|
||||||
#
|
#
|
||||||
# This source code is licensed under the BSD-style license found in the
|
# This source code is licensed under the MIT license found in the
|
||||||
# LICENSE file in the root directory of this source tree. An additional grant
|
# LICENSE file in the root directory of this source tree.
|
||||||
# of patent rights can be found in the PATENTS file in the same directory.
|
load("//tools/build_defs/oss:yoga_defs.bzl", "subdir_glob", "yoga_apple_library", "yoga_apple_test", "yoga_dep")
|
||||||
|
|
||||||
include_defs('//YOGA_DEFS')
|
|
||||||
|
|
||||||
COMPILER_FLAGS = [
|
COMPILER_FLAGS = [
|
||||||
'-fobjc-arc',
|
"-fobjc-arc",
|
||||||
'-Wconditional-uninitialized',
|
"-Wconditional-uninitialized",
|
||||||
'-Wdangling-else',
|
"-Wdangling-else",
|
||||||
'-Wdeprecated-declarations',
|
"-Wdeprecated-declarations",
|
||||||
'-Wimplicit-retain-self',
|
"-Wimplicit-retain-self",
|
||||||
'-Wincomplete-implementation',
|
"-Wincomplete-implementation",
|
||||||
'-Wobjc-method-access',
|
"-Wobjc-method-access",
|
||||||
'-Wobjc-missing-super-calls',
|
"-Wobjc-missing-super-calls",
|
||||||
'-Wmismatched-return-types',
|
"-Wmismatched-return-types",
|
||||||
'-Wreturn-type',
|
"-Wreturn-type",
|
||||||
'-Wno-global-constructors',
|
"-Wno-global-constructors",
|
||||||
'-Wno-shadow',
|
"-Wno-shadow",
|
||||||
'-Wunused-const-variable',
|
"-Wunused-const-variable",
|
||||||
'-Wunused-function',
|
"-Wunused-function",
|
||||||
'-Wunused-property-ivar',
|
"-Wunused-property-ivar",
|
||||||
'-Wunused-result',
|
"-Wunused-result",
|
||||||
'-Wunused-value',
|
"-Wunused-value",
|
||||||
]
|
]
|
||||||
|
|
||||||
apple_library(
|
yoga_apple_library(
|
||||||
name = 'YogaKit',
|
name = "YogaKit",
|
||||||
|
srcs = glob(["Source/**/*.m"]),
|
||||||
|
header_namespace = "",
|
||||||
|
exported_headers = subdir_glob(
|
||||||
|
[
|
||||||
|
("", "Source/**/*.h"),
|
||||||
|
("Source", "**/*.h"),
|
||||||
|
],
|
||||||
|
prefix = "YogaKit",
|
||||||
|
),
|
||||||
compiler_flags = COMPILER_FLAGS,
|
compiler_flags = COMPILER_FLAGS,
|
||||||
srcs = glob(['*.m']),
|
|
||||||
exported_headers = glob(['*.h']),
|
|
||||||
frameworks = [
|
frameworks = [
|
||||||
'$SDKROOT/System/Library/Frameworks/Foundation.framework',
|
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
|
||||||
'$SDKROOT/System/Library/Frameworks/UIKit.framework',
|
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
|
||||||
],
|
],
|
||||||
|
header_path_prefix = "",
|
||||||
|
link_whole = True,
|
||||||
|
visibility = ["PUBLIC"],
|
||||||
deps = [
|
deps = [
|
||||||
yoga_dep(':yoga'),
|
yoga_dep(":yoga"),
|
||||||
],
|
],
|
||||||
visibility = ['PUBLIC'],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
apple_test(
|
yoga_apple_test(
|
||||||
name = 'YogaKitTests',
|
name = "YogaKitTests",
|
||||||
|
srcs = glob(["Tests/**/*.m"]),
|
||||||
compiler_flags = COMPILER_FLAGS,
|
compiler_flags = COMPILER_FLAGS,
|
||||||
info_plist = 'Tests/Info.plist',
|
|
||||||
srcs = glob(['Tests/**/*.m']),
|
|
||||||
frameworks = [
|
frameworks = [
|
||||||
'$SDKROOT/System/Library/Frameworks/CoreGraphics.framework',
|
"$PLATFORM_DIR/Developer/Library/Frameworks/XCTest.framework",
|
||||||
'$PLATFORM_DIR/Developer/Library/Frameworks/XCTest.framework',
|
"$SDKROOT/System/Library/Frameworks/CoreGraphics.framework",
|
||||||
],
|
],
|
||||||
|
info_plist = "Tests/Info.plist",
|
||||||
|
visibility = ["PUBLIC"],
|
||||||
deps = [
|
deps = [
|
||||||
':YogaKit',
|
":YogaKit",
|
||||||
],
|
],
|
||||||
visibility = ['PUBLIC'],
|
|
||||||
)
|
)
|
||||||
|
22
YogaKit/README.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# YogaKit
|
||||||
|
|
||||||
|
[](https://cocoapods.org/pods/YogaKit)
|
||||||
|
[](https://facebook.github.io/yoga/docs/api/yogakit/)
|
||||||
|
[](https://facebook.github.io/yoga/docs/api/yogakit/)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
YogaKit is available to install via [CocoaPods](https://cocoapods.org/).
|
||||||
|
|
||||||
|
```
|
||||||
|
pod 'YogaKit', '~> 1.7'
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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.md](https://github.com/facebook/yoga/blob/master/CONTRIBUTING.md) file for how to help out.
|
35
YogaKit/Source/UIView+Yoga.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
* file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
#import "YGLayout.h"
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
typedef void (^YGLayoutConfigurationBlock)(YGLayout *layout);
|
||||||
|
|
||||||
|
@interface UIView (Yoga)
|
||||||
|
|
||||||
|
/**
|
||||||
|
The YGLayout that is attached to this view. It is lazily created.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, strong) YGLayout *yoga;
|
||||||
|
/**
|
||||||
|
Indicates whether or not Yoga is enabled
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, assign) BOOL isYogaEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
In ObjC land, every time you access `view.yoga.*` you are adding another `objc_msgSend`
|
||||||
|
to your code. If you plan on making multiple changes to YGLayout, it's more performant
|
||||||
|
to use this method, which uses a single objc_msgSend call.
|
||||||
|
*/
|
||||||
|
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block
|
||||||
|
NS_SWIFT_NAME(configureLayout(block:));
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
39
YogaKit/Source/UIView+Yoga.m
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isYogaEnabled
|
||||||
|
{
|
||||||
|
return objc_getAssociatedObject(self, kYGYogaAssociatedKey) != nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block
|
||||||
|
{
|
||||||
|
if (block != nil) {
|
||||||
|
block(self.yoga);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
16
YogaKit/Source/YGLayout+Private.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
* file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
#import "YGLayout.h"
|
||||||
|
#import <yoga/Yoga.h>
|
||||||
|
|
||||||
|
@interface YGLayout ()
|
||||||
|
|
||||||
|
@property (nonatomic, assign, readonly) YGNodeRef node;
|
||||||
|
|
||||||
|
- (instancetype)initWithView:(UIView *)view;
|
||||||
|
|
||||||
|
@end
|
169
YogaKit/Source/YGLayout.h
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
* file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import <yoga/YGEnums.h>
|
||||||
|
#import <yoga/Yoga.h>
|
||||||
|
#import <yoga/YGMacros.h>
|
||||||
|
|
||||||
|
YG_EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
extern YGValue YGPointValue(CGFloat value)
|
||||||
|
NS_SWIFT_UNAVAILABLE("Use the swift Int and FloatingPoint extensions instead");
|
||||||
|
extern YGValue YGPercentValue(CGFloat value)
|
||||||
|
NS_SWIFT_UNAVAILABLE("Use the swift Int and FloatingPoint extensions instead");
|
||||||
|
|
||||||
|
YG_EXTERN_C_END
|
||||||
|
|
||||||
|
typedef NS_OPTIONS(NSInteger, YGDimensionFlexibility) {
|
||||||
|
YGDimensionFlexibilityFlexibleWidth = 1 << 0,
|
||||||
|
YGDimensionFlexibilityFlexibleHeight = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface YGLayout : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
Make default init unavailable, as it will not initialise YGNode which is
|
||||||
|
required for the setters and getters of YGLayout's properties to work properly.
|
||||||
|
*/
|
||||||
|
- (instancetype)init
|
||||||
|
__attribute__((unavailable("you are not meant to initialise YGLayout")));
|
||||||
|
|
||||||
|
/**
|
||||||
|
Make default init unavailable, as it will not initialise YGNode which is
|
||||||
|
required for the setters and getters of YGLayout's properties to work properly.
|
||||||
|
*/
|
||||||
|
+ (instancetype)new
|
||||||
|
__attribute__((unavailable("you are not meant to initialise YGLayout")));
|
||||||
|
|
||||||
|
/**
|
||||||
|
The property that decides if we should include this view when calculating
|
||||||
|
layout. Defaults to YES.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readwrite, assign, setter=setIncludedInLayout:) BOOL isIncludedInLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The property that decides during layout/sizing whether or not styling properties should be applied.
|
||||||
|
Defaults to NO.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readwrite, assign, setter=setEnabled:) BOOL isEnabled;
|
||||||
|
|
||||||
|
@property (nonatomic, readwrite, assign) YGDirection direction;
|
||||||
|
@property (nonatomic, readwrite, assign) YGFlexDirection flexDirection;
|
||||||
|
@property (nonatomic, readwrite, assign) YGJustify justifyContent;
|
||||||
|
@property (nonatomic, readwrite, assign) YGAlign alignContent;
|
||||||
|
@property (nonatomic, readwrite, assign) YGAlign alignItems;
|
||||||
|
@property (nonatomic, readwrite, assign) YGAlign alignSelf;
|
||||||
|
@property (nonatomic, readwrite, assign) YGPositionType position;
|
||||||
|
@property (nonatomic, readwrite, assign) YGWrap flexWrap;
|
||||||
|
@property (nonatomic, readwrite, assign) YGOverflow overflow;
|
||||||
|
@property (nonatomic, readwrite, assign) YGDisplay display;
|
||||||
|
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat flex;
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat flexGrow;
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat flexShrink;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue flexBasis;
|
||||||
|
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue left;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue top;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue right;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue bottom;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue start;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue end;
|
||||||
|
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue marginLeft;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue marginTop;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue marginRight;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue marginBottom;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue marginStart;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue marginEnd;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue marginHorizontal;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue marginVertical;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue margin;
|
||||||
|
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue paddingLeft;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue paddingTop;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue paddingRight;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue paddingBottom;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue paddingStart;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue paddingEnd;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue paddingHorizontal;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue paddingVertical;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue padding;
|
||||||
|
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat borderLeftWidth;
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat borderTopWidth;
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat borderRightWidth;
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat borderBottomWidth;
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat borderStartWidth;
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat borderEndWidth;
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat borderWidth;
|
||||||
|
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue width;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue height;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue minWidth;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue minHeight;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue maxWidth;
|
||||||
|
@property (nonatomic, readwrite, assign) YGValue maxHeight;
|
||||||
|
|
||||||
|
// Yoga specific properties, not compatible with flexbox specification
|
||||||
|
@property (nonatomic, readwrite, assign) CGFloat aspectRatio;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the resolved direction of this node. This won't be YGDirectionInherit
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, assign) YGDirection resolvedDirection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Perform a layout calculation and update the frames of the views in the hierarchy with the results.
|
||||||
|
If the origin is not preserved, the root view's layout results will applied from {0,0}.
|
||||||
|
*/
|
||||||
|
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
|
||||||
|
NS_SWIFT_NAME(applyLayout(preservingOrigin:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
Perform a layout calculation and update the frames of the views in the hierarchy with the results.
|
||||||
|
If the origin is not preserved, the root view's layout results will applied from {0,0}.
|
||||||
|
*/
|
||||||
|
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
|
||||||
|
dimensionFlexibility:(YGDimensionFlexibility)dimensionFlexibility
|
||||||
|
NS_SWIFT_NAME(applyLayout(preservingOrigin:dimensionFlexibility:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the size of the view if no constraints were given. This could equivalent to calling [self
|
||||||
|
sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, assign) CGSize intrinsicSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the size of the view based on provided constraints. Pass NaN for an unconstrained dimension.
|
||||||
|
*/
|
||||||
|
- (CGSize)calculateLayoutWithSize:(CGSize)size
|
||||||
|
NS_SWIFT_NAME(calculateLayout(with:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the number of children that are using Flexbox.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, assign) NSUInteger numberOfChildren;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return a BOOL indiciating whether or not we this node contains any subviews that are included in
|
||||||
|
Yoga's layout.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, assign) BOOL isLeaf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return's a BOOL indicating if a view is dirty. When a node is dirty
|
||||||
|
it usually indicates that it will be remeasured on the next layout pass.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, assign) BOOL isDirty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Mark that a view's layout needs to be recalculated. Only works for leaf views.
|
||||||
|
*/
|
||||||
|
- (void)markDirty;
|
||||||
|
|
||||||
|
@end
|
482
YogaKit/Source/YGLayout.m
Normal file
@@ -0,0 +1,482 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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) \
|
||||||
|
- (YGValue)lowercased_name \
|
||||||
|
{ \
|
||||||
|
return YGNodeStyleGet##capitalized_name(self.node); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
- (void)set##capitalized_name:(YGValue)lowercased_name \
|
||||||
|
{ \
|
||||||
|
switch (lowercased_name.unit) { \
|
||||||
|
case YGUnitUndefined: \
|
||||||
|
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitPoint: \
|
||||||
|
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitPercent: \
|
||||||
|
YGNodeStyleSet##capitalized_name##Percent(self.node, lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
NSAssert(NO, @"Not implemented"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YG_AUTO_VALUE_PROPERTY(lowercased_name, capitalized_name) \
|
||||||
|
- (YGValue)lowercased_name \
|
||||||
|
{ \
|
||||||
|
return YGNodeStyleGet##capitalized_name(self.node); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
- (void)set##capitalized_name:(YGValue)lowercased_name \
|
||||||
|
{ \
|
||||||
|
switch (lowercased_name.unit) { \
|
||||||
|
case YGUnitPoint: \
|
||||||
|
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitPercent: \
|
||||||
|
YGNodeStyleSet##capitalized_name##Percent(self.node, lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitAuto: \
|
||||||
|
YGNodeStyleSet##capitalized_name##Auto(self.node); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
NSAssert(NO, @"Not implemented"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YG_EDGE_PROPERTY_GETTER(type, lowercased_name, capitalized_name, property, edge) \
|
||||||
|
- (type)lowercased_name \
|
||||||
|
{ \
|
||||||
|
return YGNodeStyleGet##property(self.node, edge); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge) \
|
||||||
|
- (void)set##capitalized_name:(CGFloat)lowercased_name \
|
||||||
|
{ \
|
||||||
|
YGNodeStyleSet##property(self.node, edge, lowercased_name); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YG_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
|
||||||
|
YG_EDGE_PROPERTY_GETTER(CGFloat, lowercased_name, capitalized_name, property, edge) \
|
||||||
|
YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
|
||||||
|
|
||||||
|
#define YG_VALUE_EDGE_PROPERTY_SETTER(objc_lowercased_name, objc_capitalized_name, c_name, edge) \
|
||||||
|
- (void)set##objc_capitalized_name:(YGValue)objc_lowercased_name \
|
||||||
|
{ \
|
||||||
|
switch (objc_lowercased_name.unit) { \
|
||||||
|
case YGUnitUndefined: \
|
||||||
|
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitPoint: \
|
||||||
|
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
case YGUnitPercent: \
|
||||||
|
YGNodeStyleSet##c_name##Percent(self.node, edge, objc_lowercased_name.value); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
NSAssert(NO, @"Not implemented"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YG_VALUE_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
|
||||||
|
YG_EDGE_PROPERTY_GETTER(YGValue, lowercased_name, capitalized_name, property, edge) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
|
||||||
|
|
||||||
|
#define YG_VALUE_EDGES_PROPERTIES(lowercased_name, capitalized_name) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY(lowercased_name##Left, capitalized_name##Left, capitalized_name, YGEdgeLeft) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY(lowercased_name##Top, capitalized_name##Top, capitalized_name, YGEdgeTop) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY(lowercased_name##Right, capitalized_name##Right, capitalized_name, YGEdgeRight) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY(lowercased_name##Bottom, capitalized_name##Bottom, capitalized_name, YGEdgeBottom) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY(lowercased_name##Start, capitalized_name##Start, capitalized_name, YGEdgeStart) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY(lowercased_name##End, capitalized_name##End, capitalized_name, YGEdgeEnd) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY(lowercased_name##Horizontal, capitalized_name##Horizontal, capitalized_name, YGEdgeHorizontal) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY(lowercased_name##Vertical, capitalized_name##Vertical, capitalized_name, YGEdgeVertical) \
|
||||||
|
YG_VALUE_EDGE_PROPERTY(lowercased_name, capitalized_name, capitalized_name, YGEdgeAll)
|
||||||
|
|
||||||
|
YGValue YGPointValue(CGFloat value)
|
||||||
|
{
|
||||||
|
return (YGValue) { .value = value, .unit = YGUnitPoint };
|
||||||
|
}
|
||||||
|
|
||||||
|
YGValue YGPercentValue(CGFloat value)
|
||||||
|
{
|
||||||
|
return (YGValue) { .value = value, .unit = YGUnitPercent };
|
||||||
|
}
|
||||||
|
|
||||||
|
static YGConfigRef globalConfig;
|
||||||
|
|
||||||
|
@interface YGLayout ()
|
||||||
|
|
||||||
|
@property (nonatomic, weak, readonly) UIView *view;
|
||||||
|
@property(nonatomic, assign, readonly) BOOL isUIView;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation YGLayout
|
||||||
|
|
||||||
|
@synthesize isEnabled=_isEnabled;
|
||||||
|
@synthesize isIncludedInLayout=_isIncludedInLayout;
|
||||||
|
@synthesize node=_node;
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
globalConfig = YGConfigNew();
|
||||||
|
YGConfigSetExperimentalFeatureEnabled(globalConfig, YGExperimentalFeatureWebFlexBasis, true);
|
||||||
|
YGConfigSetPointScaleFactor(globalConfig, [UIScreen mainScreen].scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithView:(UIView*)view
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
_view = view;
|
||||||
|
_node = YGNodeNewWithConfig(globalConfig);
|
||||||
|
YGNodeSetContext(_node, (__bridge void *) view);
|
||||||
|
_isEnabled = NO;
|
||||||
|
_isIncludedInLayout = YES;
|
||||||
|
_isUIView = [view isMemberOfClass:[UIView class]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
YGNodeFree(self.node);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isDirty
|
||||||
|
{
|
||||||
|
return YGNodeIsDirty(self.node);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)markDirty
|
||||||
|
{
|
||||||
|
if (self.isDirty || !self.isLeaf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Yoga is not happy if we try to mark a node as "dirty" before we have set
|
||||||
|
// the measure function. Since we already know that this is a leaf,
|
||||||
|
// this *should* be fine. Forgive me Hack Gods.
|
||||||
|
const YGNodeRef node = self.node;
|
||||||
|
if (YGNodeHasMeasureFunc(node)) {
|
||||||
|
YGNodeSetMeasureFunc(node, YGMeasureView);
|
||||||
|
}
|
||||||
|
|
||||||
|
YGNodeMarkDirty(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)numberOfChildren
|
||||||
|
{
|
||||||
|
return YGNodeGetChildCount(self.node);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isLeaf
|
||||||
|
{
|
||||||
|
NSAssert([NSThread isMainThread], @"This method must be called on the main thread.");
|
||||||
|
if (self.isEnabled) {
|
||||||
|
for (UIView *subview in self.view.subviews) {
|
||||||
|
YGLayout *const yoga = subview.yoga;
|
||||||
|
if (yoga.isEnabled && yoga.isIncludedInLayout) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Style
|
||||||
|
|
||||||
|
- (YGPositionType)position
|
||||||
|
{
|
||||||
|
return YGNodeStyleGetPositionType(self.node);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setPosition:(YGPositionType)position
|
||||||
|
{
|
||||||
|
YGNodeStyleSetPositionType(self.node, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
YG_PROPERTY(YGDirection, direction, Direction)
|
||||||
|
YG_PROPERTY(YGFlexDirection, flexDirection, FlexDirection)
|
||||||
|
YG_PROPERTY(YGJustify, justifyContent, JustifyContent)
|
||||||
|
YG_PROPERTY(YGAlign, alignContent, AlignContent)
|
||||||
|
YG_PROPERTY(YGAlign, alignItems, AlignItems)
|
||||||
|
YG_PROPERTY(YGAlign, alignSelf, AlignSelf)
|
||||||
|
YG_PROPERTY(YGWrap, flexWrap, FlexWrap)
|
||||||
|
YG_PROPERTY(YGOverflow, overflow, Overflow)
|
||||||
|
YG_PROPERTY(YGDisplay, display, Display)
|
||||||
|
|
||||||
|
YG_PROPERTY(CGFloat, flex, Flex)
|
||||||
|
YG_PROPERTY(CGFloat, flexGrow, FlexGrow)
|
||||||
|
YG_PROPERTY(CGFloat, flexShrink, FlexShrink)
|
||||||
|
YG_AUTO_VALUE_PROPERTY(flexBasis, FlexBasis)
|
||||||
|
|
||||||
|
YG_VALUE_EDGE_PROPERTY(left, Left, Position, YGEdgeLeft)
|
||||||
|
YG_VALUE_EDGE_PROPERTY(top, Top, Position, YGEdgeTop)
|
||||||
|
YG_VALUE_EDGE_PROPERTY(right, Right, Position, YGEdgeRight)
|
||||||
|
YG_VALUE_EDGE_PROPERTY(bottom, Bottom, Position, YGEdgeBottom)
|
||||||
|
YG_VALUE_EDGE_PROPERTY(start, Start, Position, YGEdgeStart)
|
||||||
|
YG_VALUE_EDGE_PROPERTY(end, End, Position, YGEdgeEnd)
|
||||||
|
YG_VALUE_EDGES_PROPERTIES(margin, Margin)
|
||||||
|
YG_VALUE_EDGES_PROPERTIES(padding, Padding)
|
||||||
|
|
||||||
|
YG_EDGE_PROPERTY(borderLeftWidth, BorderLeftWidth, Border, YGEdgeLeft)
|
||||||
|
YG_EDGE_PROPERTY(borderTopWidth, BorderTopWidth, Border, YGEdgeTop)
|
||||||
|
YG_EDGE_PROPERTY(borderRightWidth, BorderRightWidth, Border, YGEdgeRight)
|
||||||
|
YG_EDGE_PROPERTY(borderBottomWidth, BorderBottomWidth, Border, YGEdgeBottom)
|
||||||
|
YG_EDGE_PROPERTY(borderStartWidth, BorderStartWidth, Border, YGEdgeStart)
|
||||||
|
YG_EDGE_PROPERTY(borderEndWidth, BorderEndWidth, Border, YGEdgeEnd)
|
||||||
|
YG_EDGE_PROPERTY(borderWidth, BorderWidth, Border, YGEdgeAll)
|
||||||
|
|
||||||
|
YG_AUTO_VALUE_PROPERTY(width, Width)
|
||||||
|
YG_AUTO_VALUE_PROPERTY(height, Height)
|
||||||
|
YG_VALUE_PROPERTY(minWidth, MinWidth)
|
||||||
|
YG_VALUE_PROPERTY(minHeight, MinHeight)
|
||||||
|
YG_VALUE_PROPERTY(maxWidth, MaxWidth)
|
||||||
|
YG_VALUE_PROPERTY(maxHeight, MaxHeight)
|
||||||
|
YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
|
||||||
|
|
||||||
|
#pragma mark - Layout and Sizing
|
||||||
|
|
||||||
|
- (YGDirection)resolvedDirection
|
||||||
|
{
|
||||||
|
return YGNodeLayoutGetDirection(self.node);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applyLayout
|
||||||
|
{
|
||||||
|
[self calculateLayoutWithSize:self.view.bounds.size];
|
||||||
|
YGApplyLayoutToViewHierarchy(self.view, NO);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
|
||||||
|
{
|
||||||
|
[self calculateLayoutWithSize:self.view.bounds.size];
|
||||||
|
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin dimensionFlexibility:(YGDimensionFlexibility)dimensionFlexibility
|
||||||
|
{
|
||||||
|
CGSize size = self.view.bounds.size;
|
||||||
|
if (dimensionFlexibility & YGDimensionFlexibilityFlexibleWidth) {
|
||||||
|
size.width = YGUndefined;
|
||||||
|
}
|
||||||
|
if (dimensionFlexibility & YGDimensionFlexibilityFlexibleHeight) {
|
||||||
|
size.height = YGUndefined;
|
||||||
|
}
|
||||||
|
[self calculateLayoutWithSize:size];
|
||||||
|
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (CGSize)intrinsicSize
|
||||||
|
{
|
||||||
|
const CGSize constrainedSize = {
|
||||||
|
.width = YGUndefined,
|
||||||
|
.height = YGUndefined,
|
||||||
|
};
|
||||||
|
return [self calculateLayoutWithSize:constrainedSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)calculateLayoutWithSize:(CGSize)size
|
||||||
|
{
|
||||||
|
NSAssert([NSThread isMainThread], @"Yoga calculation must be done on main.");
|
||||||
|
NSAssert(self.isEnabled, @"Yoga is not enabled for this view.");
|
||||||
|
|
||||||
|
YGAttachNodesFromViewHierachy(self.view);
|
||||||
|
|
||||||
|
const YGNodeRef node = self.node;
|
||||||
|
YGNodeCalculateLayout(
|
||||||
|
node,
|
||||||
|
size.width,
|
||||||
|
size.height,
|
||||||
|
YGNodeStyleGetDirection(node));
|
||||||
|
|
||||||
|
return (CGSize) {
|
||||||
|
.width = YGNodeLayoutGetWidth(node),
|
||||||
|
.height = YGNodeLayoutGetHeight(node),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Private
|
||||||
|
|
||||||
|
static YGSize YGMeasureView(
|
||||||
|
YGNodeRef node,
|
||||||
|
float width,
|
||||||
|
YGMeasureMode widthMode,
|
||||||
|
float height,
|
||||||
|
YGMeasureMode heightMode)
|
||||||
|
{
|
||||||
|
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
|
||||||
|
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height;
|
||||||
|
|
||||||
|
UIView *view = (__bridge UIView*) YGNodeGetContext(node);
|
||||||
|
CGSize sizeThatFits = CGSizeZero;
|
||||||
|
|
||||||
|
// The default implementation of sizeThatFits: returns the existing size of
|
||||||
|
// the view. That means that if we want to layout an empty UIView, which
|
||||||
|
// already has got a frame set, its measured size should be CGSizeZero, but
|
||||||
|
// UIKit returns the existing size.
|
||||||
|
//
|
||||||
|
// See https://github.com/facebook/yoga/issues/606 for more information.
|
||||||
|
if (!view.yoga.isUIView || [view.subviews count] > 0) {
|
||||||
|
sizeThatFits = [view sizeThatFits:(CGSize){
|
||||||
|
.width = constrainedWidth,
|
||||||
|
.height = constrainedHeight,
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (YGSize) {
|
||||||
|
.width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode),
|
||||||
|
.height = YGSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static CGFloat YGSanitizeMeasurement(
|
||||||
|
CGFloat constrainedSize,
|
||||||
|
CGFloat measuredSize,
|
||||||
|
YGMeasureMode measureMode)
|
||||||
|
{
|
||||||
|
CGFloat result;
|
||||||
|
if (measureMode == YGMeasureModeExactly) {
|
||||||
|
result = constrainedSize;
|
||||||
|
} else if (measureMode == YGMeasureModeAtMost) {
|
||||||
|
result = MIN(constrainedSize, measuredSize);
|
||||||
|
} else {
|
||||||
|
result = measuredSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL YGNodeHasExactSameChildren(const YGNodeRef node, NSArray<UIView *> *subviews)
|
||||||
|
{
|
||||||
|
if (YGNodeGetChildCount(node) != subviews.count) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<subviews.count; i++) {
|
||||||
|
if (YGNodeGetChild(node, i) != subviews[i].yoga.node) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void YGAttachNodesFromViewHierachy(UIView *const view)
|
||||||
|
{
|
||||||
|
YGLayout *const yoga = view.yoga;
|
||||||
|
const YGNodeRef node = yoga.node;
|
||||||
|
|
||||||
|
// Only leaf nodes should have a measure function
|
||||||
|
if (yoga.isLeaf) {
|
||||||
|
YGRemoveAllChildren(node);
|
||||||
|
YGNodeSetMeasureFunc(node, YGMeasureView);
|
||||||
|
} else {
|
||||||
|
YGNodeSetMeasureFunc(node, NULL);
|
||||||
|
|
||||||
|
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
|
||||||
|
for (UIView *subview in view.subviews) {
|
||||||
|
if (subview.yoga.isEnabled && subview.yoga.isIncludedInLayout) {
|
||||||
|
[subviewsToInclude addObject:subview];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!YGNodeHasExactSameChildren(node, subviewsToInclude)) {
|
||||||
|
YGRemoveAllChildren(node);
|
||||||
|
for (int i=0; i<subviewsToInclude.count; i++) {
|
||||||
|
YGNodeInsertChild(node, subviewsToInclude[i].yoga.node, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UIView *const subview in subviewsToInclude) {
|
||||||
|
YGAttachNodesFromViewHierachy(subview);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void YGRemoveAllChildren(const YGNodeRef node)
|
||||||
|
{
|
||||||
|
if (node == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
YGNodeRemoveAllChildren(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CGFloat YGRoundPixelValue(CGFloat value)
|
||||||
|
{
|
||||||
|
static CGFloat scale;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^(){
|
||||||
|
scale = [UIScreen mainScreen].scale;
|
||||||
|
});
|
||||||
|
|
||||||
|
return roundf(value * scale) / scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void YGApplyLayoutToViewHierarchy(UIView *view, BOOL preserveOrigin)
|
||||||
|
{
|
||||||
|
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread.");
|
||||||
|
|
||||||
|
const YGLayout *yoga = view.yoga;
|
||||||
|
|
||||||
|
if (!yoga.isIncludedInLayout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
YGNodeRef node = yoga.node;
|
||||||
|
const CGPoint topLeft = {
|
||||||
|
YGNodeLayoutGetLeft(node),
|
||||||
|
YGNodeLayoutGetTop(node),
|
||||||
|
};
|
||||||
|
|
||||||
|
const CGPoint bottomRight = {
|
||||||
|
topLeft.x + YGNodeLayoutGetWidth(node),
|
||||||
|
topLeft.y + YGNodeLayoutGetHeight(node),
|
||||||
|
};
|
||||||
|
|
||||||
|
const CGPoint origin = preserveOrigin ? view.frame.origin : CGPointZero;
|
||||||
|
view.frame = (CGRect) {
|
||||||
|
.origin = {
|
||||||
|
.x = YGRoundPixelValue(topLeft.x + origin.x),
|
||||||
|
.y = YGRoundPixelValue(topLeft.y + origin.y),
|
||||||
|
},
|
||||||
|
.size = {
|
||||||
|
.width = YGRoundPixelValue(bottomRight.x) - YGRoundPixelValue(topLeft.x),
|
||||||
|
.height = YGRoundPixelValue(bottomRight.y) - YGRoundPixelValue(topLeft.y),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!yoga.isLeaf) {
|
||||||
|
for (NSUInteger i=0; i<view.subviews.count; i++) {
|
||||||
|
YGApplyLayoutToViewHierarchy(view.subviews[i], NO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
44
YogaKit/Source/YGLayoutExtensions.swift
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
postfix operator %
|
||||||
|
|
||||||
|
extension Int {
|
||||||
|
public static postfix func %(value: Int) -> YGValue {
|
||||||
|
return YGValue(value: Float(value), unit: .percent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Float {
|
||||||
|
public static postfix func %(value: Float) -> YGValue {
|
||||||
|
return YGValue(value: value, unit: .percent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CGFloat {
|
||||||
|
public static postfix func %(value: CGFloat) -> YGValue {
|
||||||
|
return YGValue(value: Float(value), unit: .percent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension YGValue : ExpressibleByIntegerLiteral, ExpressibleByFloatLiteral {
|
||||||
|
public init(integerLiteral value: Int) {
|
||||||
|
self = YGValue(value: Float(value), unit: .point)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(floatLiteral value: Float) {
|
||||||
|
self = YGValue(value: value, unit: .point)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(_ value: Float) {
|
||||||
|
self = YGValue(value: value, unit: .point)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(_ value: CGFloat) {
|
||||||
|
self = YGValue(value: Float(value), unit: .point)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,99 +1,260 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2014-present, Facebook, Inc.
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
* All rights reserved.
|
|
||||||
*
|
*
|
||||||
* This source code is licensed under the BSD-style license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
* LICENSE file in the root directory of this source tree.
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <XCTest/XCTest.h>
|
#import <XCTest/XCTest.h>
|
||||||
|
|
||||||
#import "UIView+Yoga.h"
|
#import <YogaKit/UIView+Yoga.h>
|
||||||
|
#import <YogaKit/YGLayout+Private.h>
|
||||||
|
#import <yoga/Yoga.h>
|
||||||
|
|
||||||
@interface YogaKitTests : XCTestCase
|
@interface YogaKitTests : XCTestCase
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation YogaKitTests
|
@implementation YogaKitTests
|
||||||
|
|
||||||
#ifndef TRAVIS_CI
|
- (void)testConfigureLayoutIsNoOpWithNilBlock
|
||||||
|
{
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
id block = nil;
|
||||||
|
XCTAssertNoThrow([view configureLayoutWithBlock:block]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testConfigureLayoutBlockWorksWithValidBlock
|
||||||
|
{
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
[view configureLayoutWithBlock:^(YGLayout *layout){
|
||||||
|
XCTAssertNotNil(layout);
|
||||||
|
layout.isEnabled = YES;
|
||||||
|
layout.width = YGPointValue(25);
|
||||||
|
}];
|
||||||
|
|
||||||
|
XCTAssertTrue(view.yoga.isEnabled);
|
||||||
|
XCTAssertEqual(view.yoga.width.value, 25);
|
||||||
|
}
|
||||||
|
|
||||||
- (void)testNodesAreDeallocedWithSingleView
|
- (void)testNodesAreDeallocedWithSingleView
|
||||||
{
|
{
|
||||||
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
__weak YGLayout *layoutRef = nil;
|
||||||
|
|
||||||
|
@autoreleasepool {
|
||||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[view yg_setFlexBasis:1];
|
view.yoga.flexBasis = YGPointValue(1);
|
||||||
XCTAssertEqual(1, YGNodeGetInstanceCount());
|
|
||||||
view = nil;
|
|
||||||
|
|
||||||
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
layoutRef = view.yoga;
|
||||||
|
XCTAssertNotNil(layoutRef);
|
||||||
|
|
||||||
|
view = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertNil(layoutRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testNodesAreDeallocedCascade
|
- (void)testNodesAreDeallocedCascade
|
||||||
{
|
{
|
||||||
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
__weak YGLayout *topLayout = nil;
|
||||||
|
__weak YGLayout *subviewLayout = nil;
|
||||||
|
|
||||||
|
@autoreleasepool {
|
||||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[view yg_setFlexBasis:1];
|
topLayout = view.yoga;
|
||||||
|
topLayout.flexBasis = YGPointValue(1);
|
||||||
|
|
||||||
for (int i=0; i<10; i++) {
|
|
||||||
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview yg_setFlexBasis:1];
|
subviewLayout = subview.yoga;
|
||||||
[view addSubview:subview];
|
subviewLayout.flexBasis = YGPointValue(1);
|
||||||
}
|
|
||||||
XCTAssertEqual(11, YGNodeGetInstanceCount());
|
|
||||||
view = nil;
|
|
||||||
|
|
||||||
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
view = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertNil(topLayout);
|
||||||
|
XCTAssertNil(subviewLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
- (void)testIsEnabled
|
||||||
|
|
||||||
- (void)testUsesYoga
|
|
||||||
{
|
{
|
||||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
XCTAssertFalse([view yg_usesYoga]);
|
XCTAssertFalse(view.yoga.isEnabled);
|
||||||
|
|
||||||
[view yg_setUsesYoga:YES];
|
view.yoga.isEnabled = YES;
|
||||||
XCTAssertTrue([view yg_usesYoga]);
|
XCTAssertTrue(view.yoga.isEnabled);
|
||||||
|
|
||||||
[view yg_setUsesYoga:NO];
|
view.yoga.isEnabled = NO;
|
||||||
XCTAssertFalse([view yg_usesYoga]);
|
XCTAssertFalse(view.yoga.isEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testSizeThatFitsAsserts
|
- (void)testSizeThatFitsAsserts
|
||||||
{
|
{
|
||||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
dispatch_sync(dispatch_queue_create("com.facebook.Yoga.testing", DISPATCH_QUEUE_SERIAL), ^(void){
|
dispatch_sync(dispatch_queue_create("com.facebook.Yoga.testing", DISPATCH_QUEUE_SERIAL), ^(void){
|
||||||
XCTAssertThrows([view yg_intrinsicSize]);
|
XCTAssertThrows(view.yoga.intrinsicSize);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testSizeThatFitsSmoke
|
- (void)testSizeThatFitsSmoke
|
||||||
{
|
{
|
||||||
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[container yg_setUsesYoga:YES];
|
container.yoga.isEnabled = YES;
|
||||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
[container yg_setAlignItems:YGAlignFlexStart];
|
container.yoga.alignItems = YGAlignFlexStart;
|
||||||
|
|
||||||
UILabel *longTextLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
UILabel *longTextLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||||
longTextLabel.text = @"This is a very very very very very very very very long piece of text.";
|
longTextLabel.text = @"This is a very very very very very very very very long piece of text.";
|
||||||
longTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
longTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||||
longTextLabel.numberOfLines = 1;
|
longTextLabel.numberOfLines = 1;
|
||||||
[longTextLabel yg_setUsesYoga:YES];
|
longTextLabel.yoga.isEnabled = YES;
|
||||||
[longTextLabel yg_setFlexShrink:1];
|
longTextLabel.yoga.flexShrink = 1;
|
||||||
[container addSubview:longTextLabel];
|
[container addSubview:longTextLabel];
|
||||||
|
|
||||||
UIView *textBadgeView = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *textBadgeView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[textBadgeView yg_setUsesYoga:YES];
|
textBadgeView.yoga.isEnabled = YES;
|
||||||
[textBadgeView yg_setMargin:3.0 forEdge:YGEdgeLeft];
|
textBadgeView.yoga.margin = YGPointValue(0);
|
||||||
[textBadgeView yg_setWidth:10];
|
textBadgeView.yoga.width = YGPointValue(10);
|
||||||
[textBadgeView yg_setHeight:10];
|
textBadgeView.yoga.height = YGPointValue(10);
|
||||||
[container addSubview:textBadgeView];
|
[container addSubview:textBadgeView];
|
||||||
|
|
||||||
const CGSize containerSize = [container yg_intrinsicSize];
|
const CGSize textBadgeViewSize = textBadgeView.yoga.intrinsicSize;
|
||||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(514,21), containerSize), @"Size is actually %@", NSStringFromCGSize(containerSize));
|
XCTAssertEqual(textBadgeViewSize.height, 10);
|
||||||
|
XCTAssertEqual(textBadgeViewSize.width, 10);
|
||||||
|
|
||||||
|
const CGSize containerSize = container.yoga.intrinsicSize;
|
||||||
|
const CGSize longTextLabelSize = longTextLabel.yoga.intrinsicSize;
|
||||||
|
|
||||||
|
XCTAssertEqual(longTextLabelSize.height, containerSize.height);
|
||||||
|
XCTAssertEqual(longTextLabelSize.width + textBadgeView.yoga.intrinsicSize.width, containerSize.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testSizeThatFitsEmptyView {
|
||||||
|
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 200, 200)];
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
const CGSize viewSize = view.yoga.intrinsicSize;
|
||||||
|
XCTAssertEqual(viewSize.height, 0);
|
||||||
|
XCTAssertEqual(viewSize.width, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testPreservingOrigin
|
||||||
|
{
|
||||||
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,75)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
view.yoga.flexBasis = YGPointValue(0);
|
||||||
|
view.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:view];
|
||||||
|
|
||||||
|
UIView *view2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
view2.yoga.isEnabled = YES;
|
||||||
|
view2.yoga.marginTop = YGPointValue(25);
|
||||||
|
view2.yoga.flexBasis = YGPointValue(0);
|
||||||
|
view2.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:view2];
|
||||||
|
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
XCTAssertEqual(50, view2.frame.origin.y);
|
||||||
|
|
||||||
|
[view2.yoga applyLayoutPreservingOrigin:NO];
|
||||||
|
XCTAssertEqual(25, view2.frame.origin.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testContainerWithFlexibleWidthGetsCorrectlySized
|
||||||
|
{
|
||||||
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
view.yoga.width = YGPointValue(100);
|
||||||
|
view.yoga.height = YGPointValue(100);
|
||||||
|
[container addSubview:view];
|
||||||
|
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES dimensionFlexibility:YGDimensionFlexibilityFlexibleWidth];
|
||||||
|
XCTAssertEqual(100, container.frame.size.width);
|
||||||
|
XCTAssertEqual(200, container.frame.size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testContainerWithFlexibleHeightGetsCorrectlySized
|
||||||
|
{
|
||||||
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
view.yoga.width = YGPointValue(100);
|
||||||
|
view.yoga.height = YGPointValue(100);
|
||||||
|
[container addSubview:view];
|
||||||
|
|
||||||
|
[container.yoga
|
||||||
|
applyLayoutPreservingOrigin:YES
|
||||||
|
dimensionFlexibility:YGDimensionFlexibilityFlexibleHeight];
|
||||||
|
XCTAssertEqual(200, container.frame.size.width);
|
||||||
|
XCTAssertEqual(100, container.frame.size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testContainerWithFlexibleWidthAndHeightGetsCorrectlySized
|
||||||
|
{
|
||||||
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
view.yoga.width = YGPointValue(100);
|
||||||
|
view.yoga.height = YGPointValue(100);
|
||||||
|
[container addSubview:view];
|
||||||
|
|
||||||
|
[container.yoga
|
||||||
|
applyLayoutPreservingOrigin:YES
|
||||||
|
dimensionFlexibility:YGDimensionFlexibilityFlexibleWidth |
|
||||||
|
YGDimensionFlexibilityFlexibleHeight];
|
||||||
|
XCTAssertEqual(100, container.frame.size.width);
|
||||||
|
XCTAssertEqual(100, container.frame.size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testMarkingDirtyOnlyWorksOnLeafNodes
|
||||||
|
{
|
||||||
|
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview.yoga.isEnabled = YES;
|
||||||
|
[container addSubview:subview];
|
||||||
|
|
||||||
|
XCTAssertFalse(container.yoga.isDirty);
|
||||||
|
[container.yoga markDirty];
|
||||||
|
XCTAssertFalse(container.yoga.isDirty);
|
||||||
|
|
||||||
|
XCTAssertFalse(subview.yoga.isDirty);
|
||||||
|
[subview.yoga markDirty];
|
||||||
|
XCTAssertTrue(subview.yoga.isDirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testThatMarkingLeafsAsDirtyWillTriggerASizeRecalculation
|
||||||
|
{
|
||||||
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 50)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
container.yoga.alignItems = YGAlignFlexStart;
|
||||||
|
|
||||||
|
UILabel *view = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||||
|
view.text = @"This is a short text.";
|
||||||
|
view.numberOfLines = 1;
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
[container addSubview:view];
|
||||||
|
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
CGSize const viewSizeAfterFirstPass = view.frame.size;
|
||||||
|
|
||||||
|
view.text = @"This is a slightly longer text.";
|
||||||
|
XCTAssertTrue(CGSizeEqualToSize(view.frame.size, viewSizeAfterFirstPass));
|
||||||
|
|
||||||
|
[view.yoga markDirty];
|
||||||
|
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
XCTAssertFalse(CGSizeEqualToSize(view.frame.size, viewSizeAfterFirstPass));
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testFrameAndOriginPlacement
|
- (void)testFrameAndOriginPlacement
|
||||||
@@ -101,21 +262,28 @@
|
|||||||
const CGSize containerSize = CGSizeMake(320, 50);
|
const CGSize containerSize = CGSizeMake(320, 50);
|
||||||
|
|
||||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
||||||
[container yg_setUsesYoga:YES];
|
container.yoga.isEnabled = YES;
|
||||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
subview1.yoga.isEnabled = YES;
|
||||||
[subview yg_setUsesYoga:YES];
|
subview1.yoga.flexGrow = 1;
|
||||||
[subview yg_setFlexGrow:1];
|
[container addSubview:subview1];
|
||||||
|
|
||||||
[container addSubview:subview];
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
}
|
subview2.yoga.isEnabled = YES;
|
||||||
[container yg_applyLayout];
|
subview2.yoga.flexGrow = 1;
|
||||||
|
[container addSubview:subview2];
|
||||||
|
|
||||||
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:0].frame, [container.subviews objectAtIndex:1].frame));
|
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:1].frame, [container.subviews objectAtIndex:2].frame));
|
subview3.yoga.isEnabled = YES;
|
||||||
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:0].frame, [container.subviews objectAtIndex:2].frame));
|
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;
|
CGFloat totalWidth = 0;
|
||||||
for (UIView *view in container.subviews) {
|
for (UIView *view in container.subviews) {
|
||||||
@@ -130,33 +298,33 @@
|
|||||||
const CGSize containerSize = CGSizeMake(300, 50);
|
const CGSize containerSize = CGSizeMake(300, 50);
|
||||||
|
|
||||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
||||||
[container yg_setUsesYoga:YES];
|
container.yoga.isEnabled = YES;
|
||||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
|
||||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview1 yg_setUsesYoga:YES];
|
subview1.yoga.isEnabled = YES;
|
||||||
[subview1 yg_setFlexGrow:1];
|
subview1.yoga.flexGrow = 1;
|
||||||
[container addSubview:subview1];
|
[container addSubview:subview1];
|
||||||
|
|
||||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview2 yg_setUsesYoga:YES];
|
subview2.yoga.isEnabled = YES;
|
||||||
[subview2 yg_setFlexGrow:1];
|
subview2.yoga.flexGrow = 1;
|
||||||
[container addSubview:subview2];
|
[container addSubview:subview2];
|
||||||
|
|
||||||
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview3 yg_setUsesYoga:YES];
|
subview3.yoga.isEnabled = YES;
|
||||||
[subview3 yg_setFlexGrow:1];
|
subview3.yoga.flexGrow = 1;
|
||||||
[container addSubview:subview3];
|
[container addSubview:subview3];
|
||||||
|
|
||||||
[container yg_applyLayout];
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
|
||||||
XCTAssertTrue(CGRectEqualToRect(subview1.frame, CGRectMake(0, 0, 100, 50)));
|
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)));
|
XCTAssertTrue(CGRectEqualToRect(subview3.frame, CGRectMake(200, 0, 100, 50)));
|
||||||
|
|
||||||
[container exchangeSubviewAtIndex:2 withSubviewAtIndex:0];
|
[container exchangeSubviewAtIndex:2 withSubviewAtIndex:0];
|
||||||
[subview2 yg_setIncludeInLayout:NO];
|
subview2.yoga.isIncludedInLayout = NO;
|
||||||
[container yg_applyLayout];
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
|
||||||
XCTAssertTrue(CGRectEqualToRect(subview3.frame, CGRectMake(0, 0, 150, 50)));
|
XCTAssertTrue(CGRectEqualToRect(subview3.frame, CGRectMake(0, 0, 150, 50)));
|
||||||
XCTAssertTrue(CGRectEqualToRect(subview1.frame, CGRectMake(150, 0, 150, 50)));
|
XCTAssertTrue(CGRectEqualToRect(subview1.frame, CGRectMake(150, 0, 150, 50)));
|
||||||
@@ -170,102 +338,417 @@
|
|||||||
const CGSize containerSize = CGSizeMake(300, 50);
|
const CGSize containerSize = CGSizeMake(300, 50);
|
||||||
|
|
||||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
||||||
[container yg_setUsesYoga:YES];
|
container.yoga.isEnabled = YES;
|
||||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
|
||||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview1 yg_setUsesYoga:YES];
|
subview1.yoga.isEnabled = YES;
|
||||||
[subview1 yg_setFlexGrow:1];
|
subview1.yoga.flexGrow = 1;
|
||||||
[container addSubview:subview1];
|
[container addSubview:subview1];
|
||||||
|
|
||||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview2 yg_setUsesYoga:YES];
|
subview2.yoga.isEnabled = YES;
|
||||||
[subview2 yg_setFlexGrow:1];
|
subview2.yoga.flexGrow = 1;
|
||||||
[container addSubview:subview2];
|
[container addSubview:subview2];
|
||||||
|
|
||||||
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview3 yg_setUsesYoga:YES];
|
subview3.yoga.isEnabled = YES;
|
||||||
[subview3 yg_setFlexGrow:1];
|
subview3.yoga.flexGrow = 1;
|
||||||
[container addSubview:subview3];
|
[container addSubview:subview3];
|
||||||
|
|
||||||
[container yg_applyLayout];
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
|
||||||
for (UIView *view in container.subviews) {
|
for (UIView *subview in container.subviews) {
|
||||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(view.bounds.size));
|
XCTAssertEqual(subview.bounds.size.width, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
[subview3 yg_setIncludeInLayout:NO];
|
subview3.yoga.isIncludedInLayout = NO;
|
||||||
[container yg_applyLayout];
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
|
||||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview1.bounds.size));
|
XCTAssertEqual(subview1.bounds.size.width, 150);
|
||||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size));
|
XCTAssertEqual(subview2.bounds.size.width, 150);
|
||||||
|
|
||||||
// We don't set the frame to zero, so, it should be set to what it was previously at.
|
// We don't set the frame to zero, so, it should be set to what it was previously at.
|
||||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview3.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview3.bounds.size));
|
XCTAssertEqual(subview3.bounds.size.width, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews
|
- (void)testThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews
|
||||||
{
|
{
|
||||||
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[container yg_setUsesYoga:YES];
|
container.yoga.isEnabled = YES;
|
||||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
|
||||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview1 yg_setUsesYoga:YES];
|
subview1.yoga.isEnabled = YES;
|
||||||
[subview1 yg_setIncludeInLayout:NO];
|
subview1.yoga.isIncludedInLayout = NO;
|
||||||
[container addSubview:subview1];
|
[container addSubview:subview1];
|
||||||
|
|
||||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview2 yg_setUsesYoga:YES];
|
subview2.yoga.isEnabled = YES;
|
||||||
[subview2 yg_setIncludeInLayout:NO];
|
subview2.yoga.isIncludedInLayout = NO;
|
||||||
[container addSubview:subview2];
|
[container addSubview:subview2];
|
||||||
|
|
||||||
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview3 yg_setUsesYoga:YES];
|
subview3.yoga.isEnabled = YES;
|
||||||
[subview3 yg_setIncludeInLayout:YES];
|
subview3.yoga.isIncludedInLayout = YES;
|
||||||
[container addSubview:subview3];
|
[container addSubview:subview3];
|
||||||
|
|
||||||
[container yg_applyLayout];
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
XCTAssertEqual(1, [container yg_numberOfChildren]);
|
XCTAssertEqual(container.yoga.numberOfChildren, 1);
|
||||||
|
|
||||||
[subview2 yg_setIncludeInLayout:YES];
|
subview2.yoga.isIncludedInLayout = YES;
|
||||||
[container yg_applyLayout];
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
XCTAssertEqual(2, [container yg_numberOfChildren]);
|
XCTAssertEqual(container.yoga.numberOfChildren, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond
|
- (void)testThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond
|
||||||
{
|
{
|
||||||
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
|
||||||
[container yg_setUsesYoga:YES];
|
container.yoga.isEnabled = YES;
|
||||||
[container yg_setFlexDirection:YGFlexDirectionRow];
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
||||||
|
|
||||||
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview1 yg_setUsesYoga:YES];
|
subview1.yoga.isEnabled = YES;
|
||||||
[subview1 yg_setFlexGrow:1];
|
subview1.yoga.flexGrow = 1;
|
||||||
[container addSubview:subview1];
|
[container addSubview:subview1];
|
||||||
|
|
||||||
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview2 yg_setUsesYoga:YES];
|
subview2.yoga.isEnabled = YES;
|
||||||
[subview2 yg_setFlexGrow:1];
|
subview2.yoga.flexGrow = 1;
|
||||||
[container addSubview:subview2];
|
[container addSubview:subview2];
|
||||||
|
|
||||||
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[subview3 yg_setUsesYoga:YES];
|
subview3.yoga.isEnabled = YES;
|
||||||
[subview3 yg_setFlexGrow:1];
|
subview3.yoga.flexGrow = 1;
|
||||||
[subview3 yg_setIncludeInLayout:NO];
|
subview3.yoga.isIncludedInLayout = NO;
|
||||||
[container addSubview:subview3];
|
[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));
|
XCTAssertEqual(subview1.bounds.size.width, 150);
|
||||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size));
|
XCTAssertEqual(subview2.bounds.size.width, 150);
|
||||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeZero, subview3.bounds.size), @"Actual size %@", NSStringFromCGSize(subview3.bounds.size));
|
XCTAssertEqual(subview3.bounds.size.width, 0);
|
||||||
|
|
||||||
[subview3 yg_setIncludeInLayout:YES];
|
subview3.yoga.isIncludedInLayout = YES;
|
||||||
[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));
|
XCTAssertEqual(subview1.bounds.size.width, 100);
|
||||||
|
XCTAssertEqual(subview2.bounds.size.width, 100);
|
||||||
|
XCTAssertEqual(subview3.bounds.size.width, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testIsLeafFlag
|
||||||
|
{
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
XCTAssertTrue(view.yoga.isLeaf);
|
||||||
|
|
||||||
|
for (int i=0; i<10; i++) {
|
||||||
|
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
[view addSubview:subview];
|
||||||
|
}
|
||||||
|
XCTAssertTrue(view.yoga.isLeaf);
|
||||||
|
|
||||||
|
view.yoga.isEnabled = YES;
|
||||||
|
view.yoga.width = YGPointValue(50);
|
||||||
|
XCTAssertTrue(view.yoga.isLeaf);
|
||||||
|
|
||||||
|
UIView *const subview = view.subviews[0];
|
||||||
|
subview.yoga.isEnabled = YES;
|
||||||
|
subview.yoga.width = YGPointValue(50);
|
||||||
|
XCTAssertFalse(view.yoga.isLeaf);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testThatWeCorrectlyAttachNestedViews
|
||||||
|
{
|
||||||
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
container.yoga.flexDirection = YGFlexDirectionColumn;
|
||||||
|
|
||||||
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview1.yoga.isEnabled = YES;
|
||||||
|
subview1.yoga.width = YGPointValue(100);
|
||||||
|
subview1.yoga.flexGrow = 1;
|
||||||
|
subview1.yoga.flexDirection = YGFlexDirectionColumn;
|
||||||
|
[container addSubview:subview1];
|
||||||
|
|
||||||
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview2.yoga.isEnabled = YES;
|
||||||
|
subview2.yoga.width = YGPointValue(150);
|
||||||
|
subview2.yoga.flexGrow = 1;
|
||||||
|
subview2.yoga.flexDirection = YGFlexDirectionColumn;
|
||||||
|
[container addSubview:subview2];
|
||||||
|
|
||||||
|
for (UIView *view in @[subview1, subview2]) {
|
||||||
|
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
someView.yoga.isEnabled = YES;
|
||||||
|
someView.yoga.flexGrow = 1;
|
||||||
|
[view addSubview:someView];
|
||||||
|
}
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
|
||||||
|
// Add the same amount of new views, reapply layout.
|
||||||
|
for (UIView *view in @[subview1, subview2]) {
|
||||||
|
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
someView.yoga.isEnabled = YES;
|
||||||
|
someView.yoga.flexGrow = 1;
|
||||||
|
[view addSubview:someView];
|
||||||
|
}
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
|
||||||
|
XCTAssertEqual(subview1.bounds.size.width, 100);
|
||||||
|
XCTAssertEqual(subview1.bounds.size.height, 25);
|
||||||
|
for (UIView *subview in subview1.subviews) {
|
||||||
|
const CGSize subviewSize = subview.bounds.size;
|
||||||
|
XCTAssertNotEqual(subviewSize.width, 0);
|
||||||
|
XCTAssertNotEqual(subviewSize.height, 0);
|
||||||
|
XCTAssertFalse(isnan(subviewSize.height));
|
||||||
|
XCTAssertFalse(isnan(subviewSize.width));
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(subview2.bounds.size.width, 150);
|
||||||
|
XCTAssertEqual(subview2.bounds.size.height, 25);
|
||||||
|
for (UIView *subview in subview2.subviews) {
|
||||||
|
const CGSize subviewSize = subview.bounds.size;
|
||||||
|
XCTAssertNotEqual(subviewSize.width, 0);
|
||||||
|
XCTAssertNotEqual(subviewSize.height, 0);
|
||||||
|
XCTAssertFalse(isnan(subviewSize.height));
|
||||||
|
XCTAssertFalse(isnan(subviewSize.width));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)testThatANonLeafNodeCanBecomeALeafNode
|
||||||
|
{
|
||||||
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
|
||||||
|
container.yoga.isEnabled = YES;
|
||||||
|
|
||||||
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview1.yoga.isEnabled = YES;
|
||||||
|
[container addSubview:subview1];
|
||||||
|
|
||||||
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
subview2.yoga.isEnabled = YES;
|
||||||
|
[subview1 addSubview:subview2];
|
||||||
|
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
[subview2 removeFromSuperview];
|
||||||
|
[container.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testPointPercent
|
||||||
|
{
|
||||||
|
XCTAssertEqual(YGPointValue(1).value, 1);
|
||||||
|
XCTAssertEqual(YGPointValue(1).unit, YGUnitPoint);
|
||||||
|
XCTAssertEqual(YGPercentValue(2).value, 2);
|
||||||
|
XCTAssertEqual(YGPercentValue(2).unit, YGUnitPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testPositionalPropertiesWork
|
||||||
|
{
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
|
||||||
|
view.yoga.left = YGPointValue(1);
|
||||||
|
XCTAssertEqual(view.yoga.left.value, 1);
|
||||||
|
XCTAssertEqual(view.yoga.left.unit, YGUnitPoint);
|
||||||
|
view.yoga.left = YGPercentValue(2);
|
||||||
|
XCTAssertEqual(view.yoga.left.value, 2);
|
||||||
|
XCTAssertEqual(view.yoga.left.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.right = YGPointValue(3);
|
||||||
|
XCTAssertEqual(view.yoga.right.value, 3);
|
||||||
|
XCTAssertEqual(view.yoga.right.unit, YGUnitPoint);
|
||||||
|
view.yoga.right = YGPercentValue(4);
|
||||||
|
XCTAssertEqual(view.yoga.right.value, 4);
|
||||||
|
XCTAssertEqual(view.yoga.right.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.top = YGPointValue(5);
|
||||||
|
XCTAssertEqual(view.yoga.top.value, 5);
|
||||||
|
XCTAssertEqual(view.yoga.top.unit, YGUnitPoint);
|
||||||
|
view.yoga.top = YGPercentValue(6);
|
||||||
|
XCTAssertEqual(view.yoga.top.value, 6);
|
||||||
|
XCTAssertEqual(view.yoga.top.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.bottom = YGPointValue(7);
|
||||||
|
XCTAssertEqual(view.yoga.bottom.value, 7);
|
||||||
|
XCTAssertEqual(view.yoga.bottom.unit, YGUnitPoint);
|
||||||
|
view.yoga.bottom = YGPercentValue(8);
|
||||||
|
XCTAssertEqual(view.yoga.bottom.value, 8);
|
||||||
|
XCTAssertEqual(view.yoga.bottom.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.start = YGPointValue(9);
|
||||||
|
XCTAssertEqual(view.yoga.start.value, 9);
|
||||||
|
XCTAssertEqual(view.yoga.start.unit, YGUnitPoint);
|
||||||
|
view.yoga.start = YGPercentValue(10);
|
||||||
|
XCTAssertEqual(view.yoga.start.value, 10);
|
||||||
|
XCTAssertEqual(view.yoga.start.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.end = YGPointValue(11);
|
||||||
|
XCTAssertEqual(view.yoga.end.value, 11);
|
||||||
|
XCTAssertEqual(view.yoga.end.unit, YGUnitPoint);
|
||||||
|
view.yoga.end = YGPercentValue(12);
|
||||||
|
XCTAssertEqual(view.yoga.end.value, 12);
|
||||||
|
XCTAssertEqual(view.yoga.end.unit, YGUnitPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testMarginPropertiesWork
|
||||||
|
{
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
|
||||||
|
view.yoga.margin = YGPointValue(1);
|
||||||
|
XCTAssertEqual(view.yoga.margin.value, 1);
|
||||||
|
XCTAssertEqual(view.yoga.margin.unit, YGUnitPoint);
|
||||||
|
view.yoga.margin = YGPercentValue(2);
|
||||||
|
XCTAssertEqual(view.yoga.margin.value, 2);
|
||||||
|
XCTAssertEqual(view.yoga.margin.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginHorizontal = YGPointValue(3);
|
||||||
|
XCTAssertEqual(view.yoga.marginHorizontal.value, 3);
|
||||||
|
XCTAssertEqual(view.yoga.marginHorizontal.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginHorizontal = YGPercentValue(4);
|
||||||
|
XCTAssertEqual(view.yoga.marginHorizontal.value, 4);
|
||||||
|
XCTAssertEqual(view.yoga.marginHorizontal.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginVertical = YGPointValue(5);
|
||||||
|
XCTAssertEqual(view.yoga.marginVertical.value, 5);
|
||||||
|
XCTAssertEqual(view.yoga.marginVertical.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginVertical = YGPercentValue(6);
|
||||||
|
XCTAssertEqual(view.yoga.marginVertical.value, 6);
|
||||||
|
XCTAssertEqual(view.yoga.marginVertical.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginLeft = YGPointValue(7);
|
||||||
|
XCTAssertEqual(view.yoga.marginLeft.value, 7);
|
||||||
|
XCTAssertEqual(view.yoga.marginLeft.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginLeft = YGPercentValue(8);
|
||||||
|
XCTAssertEqual(view.yoga.marginLeft.value, 8);
|
||||||
|
XCTAssertEqual(view.yoga.marginLeft.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginRight = YGPointValue(9);
|
||||||
|
XCTAssertEqual(view.yoga.marginRight.value, 9);
|
||||||
|
XCTAssertEqual(view.yoga.marginRight.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginRight = YGPercentValue(10);
|
||||||
|
XCTAssertEqual(view.yoga.marginRight.value, 10);
|
||||||
|
XCTAssertEqual(view.yoga.marginRight.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginTop = YGPointValue(11);
|
||||||
|
XCTAssertEqual(view.yoga.marginTop.value, 11);
|
||||||
|
XCTAssertEqual(view.yoga.marginTop.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginTop = YGPercentValue(12);
|
||||||
|
XCTAssertEqual(view.yoga.marginTop.value, 12);
|
||||||
|
XCTAssertEqual(view.yoga.marginTop.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginBottom = YGPointValue(13);
|
||||||
|
XCTAssertEqual(view.yoga.marginBottom.value, 13);
|
||||||
|
XCTAssertEqual(view.yoga.marginBottom.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginBottom = YGPercentValue(14);
|
||||||
|
XCTAssertEqual(view.yoga.marginBottom.value, 14);
|
||||||
|
XCTAssertEqual(view.yoga.marginBottom.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginStart = YGPointValue(15);
|
||||||
|
XCTAssertEqual(view.yoga.marginStart.value, 15);
|
||||||
|
XCTAssertEqual(view.yoga.marginStart.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginStart = YGPercentValue(16);
|
||||||
|
XCTAssertEqual(view.yoga.marginStart.value, 16);
|
||||||
|
XCTAssertEqual(view.yoga.marginStart.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.marginEnd = YGPointValue(17);
|
||||||
|
XCTAssertEqual(view.yoga.marginEnd.value, 17);
|
||||||
|
XCTAssertEqual(view.yoga.marginEnd.unit, YGUnitPoint);
|
||||||
|
view.yoga.marginEnd = YGPercentValue(18);
|
||||||
|
XCTAssertEqual(view.yoga.marginEnd.value, 18);
|
||||||
|
XCTAssertEqual(view.yoga.marginEnd.unit, YGUnitPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testPaddingPropertiesWork
|
||||||
|
{
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
|
||||||
|
view.yoga.padding = YGPointValue(1);
|
||||||
|
XCTAssertEqual(view.yoga.padding.value, 1);
|
||||||
|
XCTAssertEqual(view.yoga.padding.unit, YGUnitPoint);
|
||||||
|
view.yoga.padding = YGPercentValue(2);
|
||||||
|
XCTAssertEqual(view.yoga.padding.value, 2);
|
||||||
|
XCTAssertEqual(view.yoga.padding.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingHorizontal = YGPointValue(3);
|
||||||
|
XCTAssertEqual(view.yoga.paddingHorizontal.value, 3);
|
||||||
|
XCTAssertEqual(view.yoga.paddingHorizontal.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingHorizontal = YGPercentValue(4);
|
||||||
|
XCTAssertEqual(view.yoga.paddingHorizontal.value, 4);
|
||||||
|
XCTAssertEqual(view.yoga.paddingHorizontal.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingVertical = YGPointValue(5);
|
||||||
|
XCTAssertEqual(view.yoga.paddingVertical.value, 5);
|
||||||
|
XCTAssertEqual(view.yoga.paddingVertical.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingVertical = YGPercentValue(6);
|
||||||
|
XCTAssertEqual(view.yoga.paddingVertical.value, 6);
|
||||||
|
XCTAssertEqual(view.yoga.paddingVertical.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingLeft = YGPointValue(7);
|
||||||
|
XCTAssertEqual(view.yoga.paddingLeft.value, 7);
|
||||||
|
XCTAssertEqual(view.yoga.paddingLeft.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingLeft = YGPercentValue(8);
|
||||||
|
XCTAssertEqual(view.yoga.paddingLeft.value, 8);
|
||||||
|
XCTAssertEqual(view.yoga.paddingLeft.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingRight = YGPointValue(9);
|
||||||
|
XCTAssertEqual(view.yoga.paddingRight.value, 9);
|
||||||
|
XCTAssertEqual(view.yoga.paddingRight.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingRight = YGPercentValue(10);
|
||||||
|
XCTAssertEqual(view.yoga.paddingRight.value, 10);
|
||||||
|
XCTAssertEqual(view.yoga.paddingRight.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingTop = YGPointValue(11);
|
||||||
|
XCTAssertEqual(view.yoga.paddingTop.value, 11);
|
||||||
|
XCTAssertEqual(view.yoga.paddingTop.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingTop = YGPercentValue(12);
|
||||||
|
XCTAssertEqual(view.yoga.paddingTop.value, 12);
|
||||||
|
XCTAssertEqual(view.yoga.paddingTop.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingBottom = YGPointValue(13);
|
||||||
|
XCTAssertEqual(view.yoga.paddingBottom.value, 13);
|
||||||
|
XCTAssertEqual(view.yoga.paddingBottom.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingBottom = YGPercentValue(14);
|
||||||
|
XCTAssertEqual(view.yoga.paddingBottom.value, 14);
|
||||||
|
XCTAssertEqual(view.yoga.paddingBottom.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingStart = YGPointValue(15);
|
||||||
|
XCTAssertEqual(view.yoga.paddingStart.value, 15);
|
||||||
|
XCTAssertEqual(view.yoga.paddingStart.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingStart = YGPercentValue(16);
|
||||||
|
XCTAssertEqual(view.yoga.paddingStart.value, 16);
|
||||||
|
XCTAssertEqual(view.yoga.paddingStart.unit, YGUnitPercent);
|
||||||
|
|
||||||
|
view.yoga.paddingEnd = YGPointValue(17);
|
||||||
|
XCTAssertEqual(view.yoga.paddingEnd.value, 17);
|
||||||
|
XCTAssertEqual(view.yoga.paddingEnd.unit, YGUnitPoint);
|
||||||
|
view.yoga.paddingEnd = YGPercentValue(18);
|
||||||
|
XCTAssertEqual(view.yoga.paddingEnd.value, 18);
|
||||||
|
XCTAssertEqual(view.yoga.paddingEnd.unit, YGUnitPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testBorderWidthPropertiesWork
|
||||||
|
{
|
||||||
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
|
|
||||||
|
view.yoga.borderWidth = 1;
|
||||||
|
XCTAssertEqual(view.yoga.borderWidth, 1);
|
||||||
|
|
||||||
|
view.yoga.borderLeftWidth = 2;
|
||||||
|
XCTAssertEqual(view.yoga.borderLeftWidth, 2);
|
||||||
|
|
||||||
|
view.yoga.borderRightWidth = 3;
|
||||||
|
XCTAssertEqual(view.yoga.borderRightWidth, 3);
|
||||||
|
|
||||||
|
view.yoga.borderTopWidth = 4;
|
||||||
|
XCTAssertEqual(view.yoga.borderTopWidth, 4);
|
||||||
|
|
||||||
|
view.yoga.borderBottomWidth = 5;
|
||||||
|
XCTAssertEqual(view.yoga.borderBottomWidth, 5);
|
||||||
|
|
||||||
|
view.yoga.borderStartWidth = 6;
|
||||||
|
XCTAssertEqual(view.yoga.borderStartWidth, 6);
|
||||||
|
|
||||||
|
view.yoga.borderEndWidth = 7;
|
||||||
|
XCTAssertEqual(view.yoga.borderEndWidth, 7);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@@ -1,72 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2014-present, Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD-style license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
#import <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 th results
|
|
||||||
*/
|
|
||||||
- (void)yg_applyLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the size of the view if no constraints were given. This could equivalent to calling [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
|
||||||
*/
|
|
||||||
- (CGSize)yg_intrinsicSize;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the number of children that are using Flexbox.
|
|
||||||
*/
|
|
||||||
- (NSUInteger)yg_numberOfChildren;
|
|
||||||
|
|
||||||
@end
|
|
@@ -1,379 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2014-present, Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD-style license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import "UIView+Yoga.h"
|
|
||||||
|
|
||||||
#import <objc/runtime.h>
|
|
||||||
|
|
||||||
@interface YGNodeBridge : NSObject
|
|
||||||
@property (nonatomic, assign, readonly) YGNodeRef cnode;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation YGNodeBridge
|
|
||||||
|
|
||||||
+ (void)initialize
|
|
||||||
{
|
|
||||||
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 YGNodeChildCount([self ygNode]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Setters
|
|
||||||
|
|
||||||
- (void)yg_setIncludeInLayout:(BOOL)includeInLayout
|
|
||||||
{
|
|
||||||
objc_setAssociatedObject(
|
|
||||||
self,
|
|
||||||
@selector(yg_includeInLayout),
|
|
||||||
@(includeInLayout),
|
|
||||||
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setUsesYoga:(BOOL)enabled
|
|
||||||
{
|
|
||||||
objc_setAssociatedObject(
|
|
||||||
self,
|
|
||||||
@selector(yg_usesYoga),
|
|
||||||
@(enabled),
|
|
||||||
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setDirection:(YGDirection)direction
|
|
||||||
{
|
|
||||||
YGNodeStyleSetDirection([self ygNode], direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setFlexDirection:(YGFlexDirection)flexDirection
|
|
||||||
{
|
|
||||||
YGNodeStyleSetFlexDirection([self ygNode], flexDirection);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setJustifyContent:(YGJustify)justifyContent
|
|
||||||
{
|
|
||||||
YGNodeStyleSetJustifyContent([self ygNode], justifyContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setAlignContent:(YGAlign)alignContent
|
|
||||||
{
|
|
||||||
YGNodeStyleSetAlignContent([self ygNode], alignContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setAlignItems:(YGAlign)alignItems
|
|
||||||
{
|
|
||||||
YGNodeStyleSetAlignItems([self ygNode], alignItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setAlignSelf:(YGAlign)alignSelf
|
|
||||||
{
|
|
||||||
YGNodeStyleSetAlignSelf([self ygNode], alignSelf);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setPositionType:(YGPositionType)positionType
|
|
||||||
{
|
|
||||||
YGNodeStyleSetPositionType([self ygNode], positionType);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setFlexWrap:(YGWrap)flexWrap
|
|
||||||
{
|
|
||||||
YGNodeStyleSetFlexWrap([self ygNode], flexWrap);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setFlexGrow:(CGFloat)flexGrow
|
|
||||||
{
|
|
||||||
YGNodeStyleSetFlexGrow([self ygNode], flexGrow);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setFlexShrink:(CGFloat)flexShrink
|
|
||||||
{
|
|
||||||
YGNodeStyleSetFlexShrink([self ygNode], flexShrink);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setFlexBasis:(CGFloat)flexBasis
|
|
||||||
{
|
|
||||||
YGNodeStyleSetFlexBasis([self ygNode], flexBasis);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setPosition:(CGFloat)position forEdge:(YGEdge)edge
|
|
||||||
{
|
|
||||||
YGNodeStyleSetPosition([self ygNode], edge, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setMargin:(CGFloat)margin forEdge:(YGEdge)edge
|
|
||||||
{
|
|
||||||
YGNodeStyleSetMargin([self ygNode], edge, margin);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setPadding:(CGFloat)padding forEdge:(YGEdge)edge
|
|
||||||
{
|
|
||||||
YGNodeStyleSetPadding([self ygNode], edge, padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setWidth:(CGFloat)width
|
|
||||||
{
|
|
||||||
YGNodeStyleSetWidth([self ygNode], width);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setHeight:(CGFloat)height
|
|
||||||
{
|
|
||||||
YGNodeStyleSetHeight([self ygNode], height);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setMinWidth:(CGFloat)minWidth
|
|
||||||
{
|
|
||||||
YGNodeStyleSetMinWidth([self ygNode], minWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setMinHeight:(CGFloat)minHeight
|
|
||||||
{
|
|
||||||
YGNodeStyleSetMinHeight([self ygNode], minHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setMaxWidth:(CGFloat)maxWidth
|
|
||||||
{
|
|
||||||
YGNodeStyleSetMaxWidth([self ygNode], maxWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setMaxHeight:(CGFloat)maxHeight
|
|
||||||
{
|
|
||||||
YGNodeStyleSetMaxHeight([self ygNode], maxHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_setAspectRatio:(CGFloat)aspectRatio
|
|
||||||
{
|
|
||||||
YGNodeStyleSetAspectRatio([self ygNode], aspectRatio);
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Layout and Sizing
|
|
||||||
|
|
||||||
- (YGDirection)yg_resolvedDirection
|
|
||||||
{
|
|
||||||
return YGNodeLayoutGetDirection([self ygNode]);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)yg_applyLayout
|
|
||||||
{
|
|
||||||
[self calculateLayoutWithSize:self.bounds.size];
|
|
||||||
YGApplyLayoutToViewHierarchy(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGSize)yg_intrinsicSize
|
|
||||||
{
|
|
||||||
const CGSize constrainedSize = {
|
|
||||||
.width = YGUndefined,
|
|
||||||
.height = YGUndefined,
|
|
||||||
};
|
|
||||||
return [self calculateLayoutWithSize:constrainedSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Private
|
|
||||||
|
|
||||||
- (YGNodeRef)ygNode
|
|
||||||
{
|
|
||||||
YGNodeBridge *node = objc_getAssociatedObject(self, @selector(ygNode));
|
|
||||||
if (!node) {
|
|
||||||
node = [YGNodeBridge new];
|
|
||||||
YGNodeSetContext(node.cnode, (__bridge void *) self);
|
|
||||||
objc_setAssociatedObject(self, @selector(ygNode), node, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node.cnode;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGSize)calculateLayoutWithSize:(CGSize)size
|
|
||||||
{
|
|
||||||
NSAssert([NSThread isMainThread], @"YG Layout calculation must be done on main.");
|
|
||||||
NSAssert([self yg_usesYoga], @"YG Layout is not enabled for this view.");
|
|
||||||
|
|
||||||
YGAttachNodesFromViewHierachy(self);
|
|
||||||
|
|
||||||
const YGNodeRef node = [self ygNode];
|
|
||||||
YGNodeCalculateLayout(
|
|
||||||
node,
|
|
||||||
size.width,
|
|
||||||
size.height,
|
|
||||||
YGNodeStyleGetDirection(node));
|
|
||||||
|
|
||||||
return (CGSize) {
|
|
||||||
.width = YGNodeLayoutGetWidth(node),
|
|
||||||
.height = YGNodeLayoutGetHeight(node),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static YGSize YGMeasureView(
|
|
||||||
YGNodeRef node,
|
|
||||||
float width,
|
|
||||||
YGMeasureMode widthMode,
|
|
||||||
float height,
|
|
||||||
YGMeasureMode heightMode)
|
|
||||||
{
|
|
||||||
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
|
|
||||||
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height;
|
|
||||||
|
|
||||||
UIView *view = (__bridge UIView*) YGNodeGetContext(node);
|
|
||||||
const CGSize sizeThatFits = [view sizeThatFits:(CGSize) {
|
|
||||||
.width = constrainedWidth,
|
|
||||||
.height = constrainedHeight,
|
|
||||||
}];
|
|
||||||
|
|
||||||
return (YGSize) {
|
|
||||||
.width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode),
|
|
||||||
.height = YGSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static CGFloat YGSanitizeMeasurement(
|
|
||||||
CGFloat constrainedSize,
|
|
||||||
CGFloat measuredSize,
|
|
||||||
YGMeasureMode measureMode)
|
|
||||||
{
|
|
||||||
CGFloat result;
|
|
||||||
if (measureMode == YGMeasureModeExactly) {
|
|
||||||
result = constrainedSize;
|
|
||||||
} else if (measureMode == YGMeasureModeAtMost) {
|
|
||||||
result = MIN(constrainedSize, measuredSize);
|
|
||||||
} else {
|
|
||||||
result = measuredSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void YGAttachNodesFromViewHierachy(UIView *view) {
|
|
||||||
YGNodeRef node = [view ygNode];
|
|
||||||
|
|
||||||
// Only leaf nodes should have a measure function
|
|
||||||
if (![view yg_usesYoga] || view.subviews.count == 0) {
|
|
||||||
YGNodeSetMeasureFunc(node, YGMeasureView);
|
|
||||||
YGRemoveAllChildren(node);
|
|
||||||
} else {
|
|
||||||
YGNodeSetMeasureFunc(node, NULL);
|
|
||||||
|
|
||||||
// Create a list of all the subviews that we are going to use for layout.
|
|
||||||
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
|
|
||||||
for (UIView *subview in view.subviews) {
|
|
||||||
if ([subview yg_includeInLayout]) {
|
|
||||||
[subviewsToInclude addObject:subview];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL shouldReconstructChildList = NO;
|
|
||||||
if (YGNodeChildCount(node) != subviewsToInclude.count) {
|
|
||||||
shouldReconstructChildList = YES;
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < subviewsToInclude.count; i++) {
|
|
||||||
if (YGNodeGetChild(node, i) != [subviewsToInclude[i] ygNode]) {
|
|
||||||
shouldReconstructChildList = YES;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldReconstructChildList) {
|
|
||||||
YGRemoveAllChildren(node);
|
|
||||||
|
|
||||||
for (int i = 0 ; i < subviewsToInclude.count; i++) {
|
|
||||||
UIView *const subview = subviewsToInclude[i];
|
|
||||||
YGNodeInsertChild(node, [subview ygNode], i);
|
|
||||||
YGAttachNodesFromViewHierachy(subview);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void YGRemoveAllChildren(const YGNodeRef node)
|
|
||||||
{
|
|
||||||
if (node == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (YGNodeChildCount(node) > 0) {
|
|
||||||
YGNodeRemoveChild(node, YGNodeGetChild(node, YGNodeChildCount(node) - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static CGFloat YGRoundPixelValue(CGFloat value)
|
|
||||||
{
|
|
||||||
static CGFloat scale;
|
|
||||||
static dispatch_once_t onceToken;
|
|
||||||
dispatch_once(&onceToken, ^(){
|
|
||||||
scale = [UIScreen mainScreen].scale;
|
|
||||||
});
|
|
||||||
|
|
||||||
return round(value * scale) / scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void YGApplyLayoutToViewHierarchy(UIView *view) {
|
|
||||||
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread.");
|
|
||||||
if (![view yg_includeInLayout]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
YGNodeRef node = [view ygNode];
|
|
||||||
const CGPoint topLeft = {
|
|
||||||
YGNodeLayoutGetLeft(node),
|
|
||||||
YGNodeLayoutGetTop(node),
|
|
||||||
};
|
|
||||||
|
|
||||||
const CGPoint bottomRight = {
|
|
||||||
topLeft.x + YGNodeLayoutGetWidth(node),
|
|
||||||
topLeft.y + YGNodeLayoutGetHeight(node),
|
|
||||||
};
|
|
||||||
|
|
||||||
view.frame = (CGRect) {
|
|
||||||
.origin = {
|
|
||||||
.x = YGRoundPixelValue(topLeft.x),
|
|
||||||
.y = YGRoundPixelValue(topLeft.y),
|
|
||||||
},
|
|
||||||
.size = {
|
|
||||||
.width = YGRoundPixelValue(bottomRight.x) - YGRoundPixelValue(topLeft.x),
|
|
||||||
.height = YGRoundPixelValue(bottomRight.y) - YGRoundPixelValue(topLeft.y),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const BOOL isLeaf = ![view yg_usesYoga] || view.subviews.count == 0;
|
|
||||||
if (!isLeaf) {
|
|
||||||
for (NSUInteger i = 0; i < view.subviews.count; i++) {
|
|
||||||
YGApplyLayoutToViewHierarchy(view.subviews[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
6
YogaKit/YogaKitSample/Podfile
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
use_frameworks!
|
||||||
|
|
||||||
|
target 'YogaKitSample' do
|
||||||
|
pod 'YogaKit', :path => '../../YogaKit.podspec'
|
||||||
|
pod 'IGListKit', '~> 2.1.0'
|
||||||
|
end
|
26
YogaKit/YogaKitSample/Podfile.lock
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
PODS:
|
||||||
|
- IGListKit (2.1.0):
|
||||||
|
- IGListKit/Default (= 2.1.0)
|
||||||
|
- IGListKit/Default (2.1.0):
|
||||||
|
- IGListKit/Diffing
|
||||||
|
- IGListKit/Diffing (2.1.0)
|
||||||
|
- Yoga (1.7.0)
|
||||||
|
- YogaKit (1.7.0):
|
||||||
|
- Yoga (~> 1.7)
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- IGListKit (~> 2.1.0)
|
||||||
|
- YogaKit (from `../../YogaKit.podspec`)
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
YogaKit:
|
||||||
|
:path: ../../YogaKit.podspec
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
IGListKit: b826c68ef7a4ae1626c09d4d3e1ea7a169e6c36e
|
||||||
|
Yoga: 2ed1d7accfef3610a67f58c0cf101a0662137f2c
|
||||||
|
YogaKit: 31576530e8fcae3175469719ec3212397403330b
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: 216f8e7127767709e0e43f3711208d238fa5c404
|
||||||
|
|
||||||
|
COCOAPODS: 1.1.1
|
@@ -1,3 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
// !$*UTF8*$!
|
// !$*UTF8*$!
|
||||||
{
|
{
|
||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
@@ -7,21 +14,27 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* 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 */; };
|
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 */; };
|
13687D851DF87D1E00E7C260 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13687D841DF87D1E00E7C260 /* UIKit.framework */; };
|
||||||
13687D871DF87D2400E7C260 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13687D861DF87D2400E7C260 /* Foundation.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 */
|
/* 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 */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
13687D771DF878A000E7C260 /* yoga */ = {
|
13687D771DF878A000E7C260 /* yoga */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
@@ -29,9 +42,6 @@
|
|||||||
dstPath = include/yoga;
|
dstPath = include/yoga;
|
||||||
dstSubfolderSpec = 16;
|
dstSubfolderSpec = 16;
|
||||||
files = (
|
files = (
|
||||||
13687D781DF878C600E7C260 /* YGEnums.h in yoga */,
|
|
||||||
13687D791DF878C600E7C260 /* YGMacros.h in yoga */,
|
|
||||||
13687D7A1DF878C600E7C260 /* Yoga.h in yoga */,
|
|
||||||
);
|
);
|
||||||
name = yoga;
|
name = yoga;
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -42,7 +52,6 @@
|
|||||||
dstPath = include/YogaKit;
|
dstPath = include/YogaKit;
|
||||||
dstSubfolderSpec = 16;
|
dstSubfolderSpec = 16;
|
||||||
files = (
|
files = (
|
||||||
13687D7C1DF878DD00E7C260 /* UIView+Yoga.h in YogaKit */,
|
|
||||||
);
|
);
|
||||||
name = YogaKit;
|
name = YogaKit;
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -51,23 +60,19 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
13687D431DF8748400E7C260 /* YogaKitSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YogaKitSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
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>"; };
|
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>"; };
|
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; };
|
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; };
|
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 */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -77,6 +82,14 @@
|
|||||||
files = (
|
files = (
|
||||||
13687D871DF87D2400E7C260 /* Foundation.framework in Frameworks */,
|
13687D871DF87D2400E7C260 /* Foundation.framework in Frameworks */,
|
||||||
13687D851DF87D1E00E7C260 /* UIKit.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;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -86,11 +99,10 @@
|
|||||||
13687D3A1DF8748300E7C260 = {
|
13687D3A1DF8748300E7C260 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13687D5D1DF8778F00E7C260 /* yoga */,
|
|
||||||
13687D641DF8778F00E7C260 /* YogaKit */,
|
|
||||||
13687D451DF8748400E7C260 /* YogaKitSample */,
|
13687D451DF8748400E7C260 /* YogaKitSample */,
|
||||||
13687D441DF8748400E7C260 /* Products */,
|
13687D441DF8748400E7C260 /* Products */,
|
||||||
13687D831DF87D1E00E7C260 /* Frameworks */,
|
13687D831DF87D1E00E7C260 /* Frameworks */,
|
||||||
|
E1C759E3C8E84821213ECE8D /* Pods */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -98,6 +110,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13687D431DF8748400E7C260 /* YogaKitSample.app */,
|
13687D431DF8748400E7C260 /* YogaKitSample.app */,
|
||||||
|
638A944F1E215CC800A726AD /* YogaKitSampleTests.xctest */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -105,58 +118,52 @@
|
|||||||
13687D451DF8748400E7C260 /* YogaKitSample */ = {
|
13687D451DF8748400E7C260 /* YogaKitSample */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13687D491DF8748400E7C260 /* AppDelegate.h */,
|
40BD9F4E1E47902F002790A9 /* Views */,
|
||||||
13687D4A1DF8748400E7C260 /* AppDelegate.m */,
|
40BD9F481E4784B3002790A9 /* ViewControllers */,
|
||||||
13687D4C1DF8748400E7C260 /* ViewController.h */,
|
638A94471E1F06D100A726AD /* ExamplesViewController.swift */,
|
||||||
13687D4D1DF8748400E7C260 /* ViewController.m */,
|
|
||||||
13687D521DF8748400E7C260 /* Assets.xcassets */,
|
13687D521DF8748400E7C260 /* Assets.xcassets */,
|
||||||
13687D571DF8748400E7C260 /* Info.plist */,
|
13687D571DF8748400E7C260 /* Info.plist */,
|
||||||
13687D461DF8748400E7C260 /* Supporting Files */,
|
40BD9F451E477A09002790A9 /* AppDelegate.swift */,
|
||||||
);
|
);
|
||||||
path = YogaKitSample;
|
path = YogaKitSample;
|
||||||
sourceTree = "<group>";
|
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 */ = {
|
13687D831DF87D1E00E7C260 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13687D861DF87D2400E7C260 /* Foundation.framework */,
|
13687D861DF87D2400E7C260 /* Foundation.framework */,
|
||||||
13687D841DF87D1E00E7C260 /* UIKit.framework */,
|
13687D841DF87D1E00E7C260 /* UIKit.framework */,
|
||||||
|
C80A931E90C7F3088CB86822 /* Pods_YogaKitSample.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
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 */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@@ -164,11 +171,14 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 13687D5A1DF8748400E7C260 /* Build configuration list for PBXNativeTarget "YogaKitSample" */;
|
buildConfigurationList = 13687D5A1DF8748400E7C260 /* Build configuration list for PBXNativeTarget "YogaKitSample" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
513B543F92B2E4F4D1EE1CE7 /* [CP] Check Pods Manifest.lock */,
|
||||||
13687D771DF878A000E7C260 /* yoga */,
|
13687D771DF878A000E7C260 /* yoga */,
|
||||||
13687D7B1DF878CE00E7C260 /* YogaKit */,
|
13687D7B1DF878CE00E7C260 /* YogaKit */,
|
||||||
13687D3F1DF8748300E7C260 /* Sources */,
|
13687D3F1DF8748300E7C260 /* Sources */,
|
||||||
13687D401DF8748300E7C260 /* Frameworks */,
|
13687D401DF8748300E7C260 /* Frameworks */,
|
||||||
13687D411DF8748300E7C260 /* Resources */,
|
13687D411DF8748300E7C260 /* Resources */,
|
||||||
|
FA2FB9DD6471BDD3FBCE503B /* [CP] Embed Pods Frameworks */,
|
||||||
|
6E01EB987F1564F3D71EBE5A /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -179,19 +189,43 @@
|
|||||||
productReference = 13687D431DF8748400E7C260 /* YogaKitSample.app */;
|
productReference = 13687D431DF8748400E7C260 /* YogaKitSample.app */;
|
||||||
productType = "com.apple.product-type.application";
|
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 */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
13687D3B1DF8748300E7C260 /* Project object */ = {
|
13687D3B1DF8748300E7C260 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0810;
|
LastUpgradeCheck = 0820;
|
||||||
ORGANIZATIONNAME = facebook;
|
ORGANIZATIONNAME = facebook;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
13687D421DF8748300E7C260 = {
|
13687D421DF8748300E7C260 = {
|
||||||
CreatedOnToolsVersion = 8.1;
|
CreatedOnToolsVersion = 8.1;
|
||||||
|
LastSwiftMigration = 0820;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
|
638A944E1E215CC800A726AD = {
|
||||||
|
CreatedOnToolsVersion = 8.2.1;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
|
TestTargetID = 13687D421DF8748300E7C260;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 13687D3E1DF8748300E7C260 /* Build configuration list for PBXProject "YogaKitSample" */;
|
buildConfigurationList = 13687D3E1DF8748300E7C260 /* Build configuration list for PBXProject "YogaKitSample" */;
|
||||||
@@ -208,6 +242,7 @@
|
|||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
13687D421DF8748300E7C260 /* YogaKitSample */,
|
13687D421DF8748300E7C260 /* YogaKitSample */,
|
||||||
|
638A944E1E215CC800A726AD /* YogaKitSampleTests */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@@ -221,24 +256,93 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
638A944D1E215CC800A726AD /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* 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 */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
13687D3F1DF8748300E7C260 /* Sources */ = {
|
13687D3F1DF8748300E7C260 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
13687D801DF87CEC00E7C260 /* UIView+Yoga.m in Sources */,
|
40BD9F501E479079002790A9 /* SingleLabelCollectionCell.swift in Sources */,
|
||||||
13687D4E1DF8748400E7C260 /* ViewController.m in Sources */,
|
40BD9F521E479173002790A9 /* LayoutInclusionViewController.swift in Sources */,
|
||||||
13687D4B1DF8748400E7C260 /* AppDelegate.m in Sources */,
|
638A94481E1F06D100A726AD /* ExamplesViewController.swift in Sources */,
|
||||||
13687D821DF87CF200E7C260 /* Yoga.c in Sources */,
|
40BD9F4B1E47850C002790A9 /* BasicViewController.swift in Sources */,
|
||||||
13687D811DF87CF200E7C260 /* YGNodeList.c in Sources */,
|
40BD9F461E477A09002790A9 /* AppDelegate.swift in Sources */,
|
||||||
13687D481DF8748400E7C260 /* main.m in Sources */,
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
638A944B1E215CC800A726AD /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
638A94551E215CC800A726AD /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 13687D421DF8748300E7C260 /* YogaKitSample */;
|
||||||
|
targetProxy = 638A94541E215CC800A726AD /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
13687D581DF8748400E7C260 /* Debug */ = {
|
13687D581DF8748400E7C260 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
@@ -258,6 +362,7 @@
|
|||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
@@ -305,6 +410,7 @@
|
|||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
@@ -330,23 +436,60 @@
|
|||||||
};
|
};
|
||||||
13687D5B1DF8748400E7C260 /* Debug */ = {
|
13687D5B1DF8748400E7C260 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 1D2FF4D5FCA6A8C54A4074A3 /* Pods-YogaKitSample.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
INFOPLIST_FILE = YogaKitSample/Info.plist;
|
INFOPLIST_FILE = YogaKitSample/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_INSTALL_OBJC_HEADER = NO;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
13687D5C1DF8748400E7C260 /* Release */ = {
|
13687D5C1DF8748400E7C260 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 82F0896A88112E957EF37C7F /* Pods-YogaKitSample.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
INFOPLIST_FILE = YogaKitSample/Info.plist;
|
INFOPLIST_FILE = YogaKitSample/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
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;
|
name = Release;
|
||||||
};
|
};
|
||||||
@@ -369,6 +512,16 @@
|
|||||||
13687D5C1DF8748400E7C260 /* Release */,
|
13687D5C1DF8748400E7C260 /* Release */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
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 */
|
/* End XCConfigurationList section */
|
||||||
};
|
};
|
||||||
|
@@ -1,3 +1,10 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
|
||||||
|
This source code is licensed under the MIT license found in the
|
||||||
|
LICENSE file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Workspace
|
<Workspace
|
||||||
version = "1.0">
|
version = "1.0">
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0810"
|
LastUpgradeVersion = "0820"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -28,6 +28,16 @@
|
|||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "638A944E1E215CC800A726AD"
|
||||||
|
BuildableName = "YogaKitSampleTests.xctest"
|
||||||
|
BlueprintName = "YogaKitSampleTests"
|
||||||
|
ReferencedContainer = "container:YogaKitSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
</Testables>
|
</Testables>
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>SchemeUserState</key>
|
|
||||||
<dict>
|
|
||||||
<key>YogaKitSample.xcscheme</key>
|
|
||||||
<dict>
|
|
||||||
<key>orderHint</key>
|
|
||||||
<integer>0</integer>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>SuppressBuildableAutocreation</key>
|
|
||||||
<dict>
|
|
||||||
<key>13687D421DF8748300E7C260</key>
|
|
||||||
<dict>
|
|
||||||
<key>primary</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
17
YogaKit/YogaKitSample/YogaKitSample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
|
||||||
|
This source code is licensed under the MIT license found in the
|
||||||
|
LICENSE file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<?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>
|
@@ -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
|
|
||||||
|
|
@@ -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
|
|
27
YogaKit/YogaKitSample/YogaKitSample/AppDelegate.swift
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the license found in the
|
||||||
|
* LICENSE-examples file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@UIApplicationMain
|
||||||
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
var window: UIWindow?
|
||||||
|
|
||||||
|
func applicationDidFinishLaunching(_ application: UIApplication) {
|
||||||
|
self.window = UIWindow(frame: UIScreen.main.bounds)
|
||||||
|
if let window = self.window {
|
||||||
|
let navigationController = UINavigationController(rootViewController: ExamplesViewController())
|
||||||
|
navigationController.navigationBar.isTranslucent = false
|
||||||
|
|
||||||
|
window.rootViewController = navigationController
|
||||||
|
window.backgroundColor = .white
|
||||||
|
window.makeKeyAndVisible()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,43 +1,69 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "iphone",
|
|
||||||
"size" : "20x20",
|
"size" : "20x20",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Yoga-20x20@2x.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "iphone",
|
|
||||||
"size" : "20x20",
|
"size" : "20x20",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Yoga-20x20@3x.png",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "iphone",
|
|
||||||
"size" : "29x29",
|
"size" : "29x29",
|
||||||
"scale" : "2x"
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Yoga-29x29@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "iphone",
|
|
||||||
"size" : "29x29",
|
"size" : "29x29",
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"size" : "40x40",
|
"filename" : "Yoga-29x29@2x.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"size" : "29x29",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"size" : "40x40",
|
"filename" : "Yoga-29x29@3x.png",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"size" : "40x40",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"size" : "60x60",
|
"filename" : "Yoga-40x40@2x.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"size" : "40x40",
|
||||||
"idiom" : "iphone",
|
"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",
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Yoga-60x60@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Yoga-60x60@3x.png",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 868 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 7.4 KiB |
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
100
YogaKit/YogaKitSample/YogaKitSample/ExamplesViewController.swift
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the license found in the
|
||||||
|
* LICENSE-examples file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import IGListKit
|
||||||
|
|
||||||
|
private final class ExampleModel {
|
||||||
|
let title: String
|
||||||
|
let controllerClass: UIViewController.Type
|
||||||
|
|
||||||
|
init(title: String, controllerClass: UIViewController.Type) {
|
||||||
|
self.title = title
|
||||||
|
self.controllerClass = controllerClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ExampleModel: IGListDiffable {
|
||||||
|
fileprivate func diffIdentifier() -> NSObjectProtocol {
|
||||||
|
return title as NSString
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func isEqual(toDiffableObject object: IGListDiffable?) -> Bool {
|
||||||
|
guard let otherObj = object as? ExampleModel else { return false }
|
||||||
|
|
||||||
|
return (title == otherObj.title) &&
|
||||||
|
(controllerClass == otherObj.controllerClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class ExamplesViewController: UIViewController, IGListAdapterDataSource, IGListSingleSectionControllerDelegate {
|
||||||
|
private lazy var adapter: IGListAdapter = {
|
||||||
|
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
|
||||||
|
}()
|
||||||
|
private let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
|
||||||
|
|
||||||
|
|
||||||
|
// Update this to array to create more examples.
|
||||||
|
private let models: [ExampleModel] = [ExampleModel(title: "Basic Layout", controllerClass: BasicViewController.self),
|
||||||
|
ExampleModel(title: "Exclude Views in Layout", controllerClass: LayoutInclusionViewController.self)]
|
||||||
|
|
||||||
|
//MARK: UIViewController
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
title = "Examples"
|
||||||
|
view.addSubview(collectionView)
|
||||||
|
adapter.collectionView = collectionView
|
||||||
|
adapter.dataSource = self
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidLayoutSubviews() {
|
||||||
|
super.viewDidLayoutSubviews()
|
||||||
|
collectionView.frame = view.bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: IGListAdapterDataSource
|
||||||
|
|
||||||
|
func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
|
||||||
|
return models as [IGListDiffable]
|
||||||
|
}
|
||||||
|
|
||||||
|
func listAdapter(_ listAdapter: IGListAdapter, sectionControllerFor object: Any) -> IGListSectionController {
|
||||||
|
let sizeBlock: IGListSingleSectionCellSizeBlock = { (model, context) in
|
||||||
|
return CGSize(width: (context?.containerSize.width)!, height: 75.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
let configureBlock: IGListSingleSectionCellConfigureBlock = { (model, cell) in
|
||||||
|
guard let m = model as? ExampleModel, let c = cell as? SingleLabelCollectionCell else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.label.text = m.title
|
||||||
|
}
|
||||||
|
|
||||||
|
let sectionController = IGListSingleSectionController(cellClass: SingleLabelCollectionCell.self,
|
||||||
|
configureBlock: configureBlock,
|
||||||
|
sizeBlock: sizeBlock)
|
||||||
|
sectionController.selectionDelegate = self
|
||||||
|
return sectionController
|
||||||
|
}
|
||||||
|
|
||||||
|
func emptyView(for listAdapter: IGListAdapter) -> UIView? { return nil }
|
||||||
|
|
||||||
|
//MARK: IGListSingleSectionControllerDelegate
|
||||||
|
|
||||||
|
func didSelect(_ sectionController: IGListSingleSectionController) {
|
||||||
|
let section = adapter.section(for: sectionController)
|
||||||
|
let model = models[section]
|
||||||
|
|
||||||
|
let controller = model.controllerClass.init()
|
||||||
|
controller.title = model.title
|
||||||
|
|
||||||
|
self.navigationController?.pushViewController(controller, animated: true)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
|
root.backgroundColor = .red
|
||||||
|
root.yoga.isEnabled = true
|
||||||
|
root.yoga.width = YGValue(self.view.bounds.size.width)
|
||||||
|
root.yoga.height = YGValue(self.view.bounds.size.height)
|
||||||
|
root.yoga.alignItems = .center
|
||||||
|
}
|
||||||
|
|
||||||
|
final class SwiftViewController: UIViewController, IGListAdapterDataSource {
|
||||||
|
|
||||||
|
lazy var adapter: IGListAdapter = {
|
||||||
|
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
|
||||||
|
}()
|
||||||
|
let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
|
||||||
|
|
||||||
|
//MARK: UIViewController
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
title = "YogaKit Examples"
|
||||||
|
view.addSubview(collectionView)
|
||||||
|
adapter.collectionView = collectionView
|
||||||
|
adapter.dataSource = self
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidLayoutSubviews() {
|
||||||
|
super.viewDidLayoutSubviews()
|
||||||
|
collectionView.frame = view.bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//MARK: IGListAdapterDataSource
|
||||||
|
|
||||||
|
func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
|
||||||
|
return ["Dustin" as IGListDiffable, "Ryan" as IGListDiffable]
|
||||||
|
}
|
||||||
|
|
||||||
|
func listAdapter(_ listAdapter: IGListAdapter, sectionControllerFor object: Any) -> IGListSectionController {
|
||||||
|
let sizeBlock: IGListSingleSectionCellSizeBlock = { (model, context) in
|
||||||
|
return CGSize(width: (context?.containerSize.width)!, height: 100.0)
|
||||||
|
}
|
||||||
|
let configureBlock: IGListSingleSectionCellConfigureBlock = { (model, cell) in
|
||||||
|
guard let m = model as? String else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.backgroundColor = (m == "Dustin") ? .blue : .red
|
||||||
|
}
|
||||||
|
|
||||||
|
return IGListSingleSectionController(cellClass: UICollectionViewCell.self,
|
||||||
|
configureBlock: configureBlock,
|
||||||
|
sizeBlock: sizeBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
func emptyView(for listAdapter: IGListAdapter) -> UIView? {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
@@ -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
|
|
||||||
|
|
@@ -10,27 +10,23 @@
|
|||||||
|
|
||||||
#import <YogaKit/UIView+Yoga.h>
|
#import <YogaKit/UIView+Yoga.h>
|
||||||
|
|
||||||
@interface ViewController ()
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation ViewController
|
@implementation ViewController
|
||||||
|
|
||||||
- (void)viewDidLoad
|
- (void)viewDidLoad
|
||||||
{
|
{
|
||||||
UIView *root = self.view;
|
UIView *root = self.view;
|
||||||
root.backgroundColor = [UIColor redColor];
|
root.backgroundColor = [UIColor redColor];
|
||||||
[root yg_setUsesYoga:YES];
|
root.yoga.isEnabled = YES;
|
||||||
[root yg_setWidth:self.view.bounds.size.width];
|
root.yoga.width = YGPointValue(self.view.bounds.size.width);
|
||||||
[root yg_setHeight:self.view.bounds.size.height];
|
root.yoga.height = YGPointValue(self.view.bounds.size.height);
|
||||||
[root yg_setAlignItems:YGAlignCenter];
|
root.yoga.alignItems = YGAlignCenter;
|
||||||
[root yg_setJustifyContent:YGJustifyCenter];
|
root.yoga.justifyContent = YGJustifyCenter;
|
||||||
|
|
||||||
UIView *child1 = [UIView new];
|
UIView *child1 = [UIView new];
|
||||||
child1.backgroundColor = [UIColor blueColor];
|
child1.backgroundColor = [UIColor blueColor];
|
||||||
[child1 yg_setUsesYoga:YES];
|
child1.yoga.isEnabled = YES;
|
||||||
[child1 yg_setWidth:100];
|
child1.yoga.width = YGPointValue(100);
|
||||||
[child1 yg_setHeight:100];
|
child1.yoga.height = YGPointValue(100);
|
||||||
|
|
||||||
UIView *child2 = [UIView new];
|
UIView *child2 = [UIView new];
|
||||||
child2.backgroundColor = [UIColor greenColor];
|
child2.backgroundColor = [UIColor greenColor];
|
||||||
@@ -53,7 +49,7 @@
|
|||||||
[child2 addSubview:child3];
|
[child2 addSubview:child3];
|
||||||
[root addSubview:child1];
|
[root addSubview:child1];
|
||||||
[root addSubview:child2];
|
[root addSubview:child2];
|
||||||
[root yg_applyLayout];
|
[root.yoga applyLayoutPreservingOrigin:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* 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.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.width = YGValue(containerSize.width)
|
||||||
|
layout.height = YGValue(containerSize.height)
|
||||||
|
layout.alignItems = .center
|
||||||
|
layout.justifyContent = .center
|
||||||
|
}
|
||||||
|
|
||||||
|
let child1 = UIView()
|
||||||
|
child1.backgroundColor = .blue
|
||||||
|
child1.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.width = 100
|
||||||
|
layout.height = 10
|
||||||
|
layout.marginBottom = 25
|
||||||
|
}
|
||||||
|
root.addSubview(child1)
|
||||||
|
|
||||||
|
let child2 = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
|
||||||
|
child2.backgroundColor = .green
|
||||||
|
child2.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.alignSelf = .flexEnd
|
||||||
|
}
|
||||||
|
root.addSubview(child2)
|
||||||
|
|
||||||
|
let child3 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
|
||||||
|
child3.backgroundColor = .yellow
|
||||||
|
child3.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.alignSelf = .flexStart
|
||||||
|
}
|
||||||
|
root.addSubview(child3)
|
||||||
|
|
||||||
|
root.yoga.applyLayout(preservingOrigin: true)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* 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.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.flexDirection = .column
|
||||||
|
layout.justifyContent = .spaceAround
|
||||||
|
}
|
||||||
|
|
||||||
|
contentView.backgroundColor = .clear
|
||||||
|
contentView.layer.borderColor = UIColor.lightGray.cgColor
|
||||||
|
contentView.layer.borderWidth = 1.0
|
||||||
|
contentView.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.height = 300
|
||||||
|
layout.width = YGValue(self.view.bounds.size.width)
|
||||||
|
layout.flexDirection = .row
|
||||||
|
layout.justifyContent = .center
|
||||||
|
layout.paddingHorizontal = 25
|
||||||
|
}
|
||||||
|
self.view.addSubview(contentView)
|
||||||
|
|
||||||
|
let redView = UIView(frame: .zero)
|
||||||
|
redView.backgroundColor = .red
|
||||||
|
redView.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.flexGrow = 1
|
||||||
|
layout.flexShrink = 1
|
||||||
|
}
|
||||||
|
contentView.addSubview(redView)
|
||||||
|
|
||||||
|
disappearingView.backgroundColor = .blue
|
||||||
|
disappearingView.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.flexGrow = 1
|
||||||
|
}
|
||||||
|
contentView.addSubview(disappearingView)
|
||||||
|
|
||||||
|
button.setTitle("Add Blue View", for: UIControlState.selected)
|
||||||
|
button.setTitle("Remove Blue View", for: UIControlState.normal)
|
||||||
|
button.addTarget(self, action: #selector(buttonWasTapped), for: UIControlEvents.touchUpInside)
|
||||||
|
button.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.height = 300
|
||||||
|
layout.width = 300
|
||||||
|
layout.alignSelf = .center
|
||||||
|
}
|
||||||
|
root.addSubview(button)
|
||||||
|
|
||||||
|
root.yoga.applyLayout(preservingOrigin: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK - UIButton Action
|
||||||
|
func buttonWasTapped() {
|
||||||
|
button.isSelected = !button.isSelected
|
||||||
|
|
||||||
|
button.isUserInteractionEnabled = false
|
||||||
|
disappearingView.yoga.isIncludedInLayout = !disappearingView.yoga.isIncludedInLayout
|
||||||
|
disappearingView.isHidden = !disappearingView.isHidden
|
||||||
|
|
||||||
|
contentView.yoga.applyLayout(preservingOrigin: true)
|
||||||
|
button.isUserInteractionEnabled = true
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* 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.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.flexDirection = .column
|
||||||
|
layout.justifyContent = .flexEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
label.textAlignment = .center
|
||||||
|
label.numberOfLines = 1
|
||||||
|
label.yoga.isIncludedInLayout = false
|
||||||
|
contentView.addSubview(label)
|
||||||
|
|
||||||
|
let border = UIView(frame: .zero)
|
||||||
|
border.backgroundColor = .lightGray
|
||||||
|
border.configureLayout { (layout) in
|
||||||
|
layout.isEnabled = true
|
||||||
|
layout.height = 0.5
|
||||||
|
layout.marginHorizontal = 25
|
||||||
|
}
|
||||||
|
contentView.addSubview(border)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
|
||||||
|
contentView.yoga.applyLayout(preservingOrigin: false)
|
||||||
|
label.frame = contentView.bounds
|
||||||
|
}
|
||||||
|
}
|
@@ -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]));
|
|
||||||
}
|
|
||||||
}
|
|
30
android/BUCK
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_RES_TARGET", "INFER_ANNOTATIONS_TARGET", "JAVA_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "yoga_android_aar", "yoga_android_resource")
|
||||||
|
|
||||||
|
yoga_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,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
yoga_android_resource(
|
||||||
|
name = "res",
|
||||||
|
package = "com.facebook.yoga.android",
|
||||||
|
res = "src/main/res",
|
||||||
|
visibility = [
|
||||||
|
"PUBLIC",
|
||||||
|
],
|
||||||
|
)
|
21
android/README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# YogaLayout [](https://facebook.github.io/yoga/docs/api/android/) [](https://facebook.github.io/yoga/docs/api/android/) [](https://bintray.com/facebook/maven/com.facebook.yoga.android%3Ayoga-layout/_latestVersion)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
YogaLayout is available via jcenter:
|
||||||
|
|
||||||
|
compile 'com.facebook.yoga.android:yoga-layout:1.2.0'
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Check out the docs [here](https://facebook.github.io/yoga/docs/api/android/).
|
||||||
|
|
||||||
|
We also have a sample project. To try it, clone the repo and run (with a device attached)
|
||||||
|
|
||||||
|
buck install -r android/sample
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
We welcome all pull-requests! At Facebook we sync the open source version of YogaKit daily, so we're always testing the latest changes.
|
||||||
|
|
||||||
|
See the CONTRIBUTING file for how to help out.
|
52
android/build.gradle
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
apply plugin: 'com.jfrog.bintray'
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
apply plugin: 'com.github.dcendents.android-maven'
|
||||||
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
|
version = VERSION_NAME
|
||||||
|
group = GROUP
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion rootProject.compileSdkVersion
|
||||||
|
buildToolsVersion rootProject.buildToolsVersion
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion rootProject.minSdkVersion
|
||||||
|
targetSdkVersion rootProject.targetSdkVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
targetCompatibility rootProject.targetCompatibilityVersion
|
||||||
|
sourceCompatibility rootProject.sourceCompatibilityVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api project(':yoga')
|
||||||
|
}
|
||||||
|
|
||||||
|
task sourcesJar(type: Jar) {
|
||||||
|
classifier = 'source'
|
||||||
|
from android.sourceSets.main.java.srcDirs
|
||||||
|
}
|
||||||
|
|
||||||
|
task javadoc(type: Javadoc) {
|
||||||
|
failOnError false
|
||||||
|
source = android.sourceSets.main.java.sourceFiles
|
||||||
|
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
|
||||||
|
classpath += configurations.compile
|
||||||
|
}
|
||||||
|
|
||||||
|
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||||
|
classifier = 'javadoc'
|
||||||
|
from javadoc.destinationDir
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: rootProject.file('gradle/release.gradle')
|
12
android/gradle.properties
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
# file in the root directory of this source tree.
|
||||||
|
#
|
||||||
|
|
||||||
|
GROUP=com.facebook.yoga.android
|
||||||
|
POM_NAME=YogaLayout
|
||||||
|
POM_DESCRIPTION=YogaLayout
|
||||||
|
POM_ARTIFACT_ID=yoga-layout
|
||||||
|
POM_PACKAGING=aar
|
54
android/sample/AndroidManifest.xml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<?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"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:allowBackup="false"
|
||||||
|
android:theme="@style/NoTitleBarWhiteBG"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:exported="true"
|
||||||
|
>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".BenchmarkActivity"
|
||||||
|
android:exported="false"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
36
android/sample/BUCK
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native")
|
||||||
|
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_RES_TARGET", "ANDROID_SAMPLE_JAVA_TARGET", "ANDROID_SAMPLE_RES_TARGET", "yoga_android_binary", "yoga_android_resource")
|
||||||
|
|
||||||
|
yoga_android_binary(
|
||||||
|
name = "sample",
|
||||||
|
keystore = ":debug_keystore",
|
||||||
|
manifest = "AndroidManifest.xml",
|
||||||
|
deps = [
|
||||||
|
ANDROID_SAMPLE_JAVA_TARGET,
|
||||||
|
ANDROID_SAMPLE_RES_TARGET,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
yoga_android_resource(
|
||||||
|
name = "res",
|
||||||
|
package = "com.facebook.samples.yoga",
|
||||||
|
res = "res",
|
||||||
|
visibility = [
|
||||||
|
"PUBLIC",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
ANDROID_RES_TARGET,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
fb_native.keystore(
|
||||||
|
name = "debug_keystore",
|
||||||
|
properties = "debug.keystore.properties",
|
||||||
|
store = "debug.keystore",
|
||||||
|
)
|
BIN
android/sample/debug.keystore
Normal file
3
android/sample/debug.keystore.properties
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
key.alias=androiddebugkey
|
||||||
|
key.store.password=android
|
||||||
|
key.alias.password=android
|
21
android/sample/java/com/facebook/samples/yoga/BUCK
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the license found in the
|
||||||
|
# LICENSE-examples file in the root directory of this source tree.
|
||||||
|
|
||||||
|
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_SAMPLE_RES_TARGET", "ANDROID_SUPPORT_TARGET", "APPCOMPAT_TARGET", "SOLOADER_TARGET", "yoga_android_library")
|
||||||
|
|
||||||
|
yoga_android_library(
|
||||||
|
name = "yoga",
|
||||||
|
srcs = glob(["**/*.java"]),
|
||||||
|
visibility = [
|
||||||
|
"PUBLIC",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
ANDROID_JAVA_TARGET,
|
||||||
|
ANDROID_SAMPLE_RES_TARGET,
|
||||||
|
ANDROID_SUPPORT_TARGET,
|
||||||
|
APPCOMPAT_TARGET,
|
||||||
|
SOLOADER_TARGET,
|
||||||
|
],
|
||||||
|
)
|
@@ -0,0 +1,113 @@
|
|||||||
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v4.app.FragmentPagerAdapter;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentTransaction;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
import com.facebook.yoga.android.YogaViewLayoutFactory;
|
||||||
|
|
||||||
|
public class BenchmarkActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
LayoutInflater.from(this).setFactory(YogaViewLayoutFactory.getInstance());
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setContentView(R.layout.benchmark_select_layout);
|
||||||
|
|
||||||
|
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
|
||||||
|
viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager()));
|
||||||
|
|
||||||
|
final ActionBar actionBar = getSupportActionBar();
|
||||||
|
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||||
|
|
||||||
|
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
|
||||||
|
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
|
||||||
|
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
|
||||||
|
viewPager.setCurrentItem(tab.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
actionBar.addTab(
|
||||||
|
actionBar.newTab()
|
||||||
|
.setText("Inflate")
|
||||||
|
.setTabListener(tabListener));
|
||||||
|
actionBar.addTab(
|
||||||
|
actionBar.newTab()
|
||||||
|
.setText("Measure")
|
||||||
|
.setTabListener(tabListener));
|
||||||
|
actionBar.addTab(
|
||||||
|
actionBar.newTab()
|
||||||
|
.setText("Layout")
|
||||||
|
.setTabListener(tabListener));
|
||||||
|
|
||||||
|
viewPager.setOnPageChangeListener(
|
||||||
|
new ViewPager.SimpleOnPageChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onPageSelected(int position) {
|
||||||
|
// When swiping between pages, select the
|
||||||
|
// corresponding tab.
|
||||||
|
actionBar.setSelectedNavigationItem(position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
viewPager.setOffscreenPageLimit(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.action_bar_benchmark, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
// There is only one option
|
||||||
|
Intent intent = new Intent(this, MainActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
this.finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PagerAdapter extends FragmentPagerAdapter {
|
||||||
|
public PagerAdapter(FragmentManager fm) {
|
||||||
|
super(fm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment getItem(int i) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
return new BenchmarkInflate();
|
||||||
|
case 1:
|
||||||
|
return new BenchmarkMeasure();
|
||||||
|
default:
|
||||||
|
return new BenchmarkLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,193 @@
|
|||||||
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.lang.Math;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.os.Environment;
|
||||||
|
|
||||||
|
import static java.util.Collections.sort;
|
||||||
|
|
||||||
|
public class BenchmarkAggregator {
|
||||||
|
|
||||||
|
private final int GRAPH_WIDTH = 30;
|
||||||
|
private final int GRAPH_HEIGHT = 6;
|
||||||
|
|
||||||
|
private List<Long> times;
|
||||||
|
private boolean tracing;
|
||||||
|
private long lastTraceStart;
|
||||||
|
|
||||||
|
private boolean statsFresh;
|
||||||
|
private long mean;
|
||||||
|
private long variance;
|
||||||
|
private long stddev;
|
||||||
|
private long min;
|
||||||
|
private long max;
|
||||||
|
private long p10;
|
||||||
|
private long p50;
|
||||||
|
private long p90;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public BenchmarkAggregator(String name) {
|
||||||
|
times = new ArrayList<>();
|
||||||
|
tracing = false;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startTrace() {
|
||||||
|
if (tracing) {
|
||||||
|
throw new RuntimeException("Cannot start trace while running previous one");
|
||||||
|
}
|
||||||
|
tracing = true;
|
||||||
|
lastTraceStart = System.nanoTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endTrace() {
|
||||||
|
if (!tracing) {
|
||||||
|
throw new RuntimeException("Cannot stop trace if none are running!");
|
||||||
|
}
|
||||||
|
times.add(System.nanoTime() - lastTraceStart);
|
||||||
|
tracing = false;
|
||||||
|
statsFresh = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeStats() {
|
||||||
|
if (statsFresh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(times);
|
||||||
|
|
||||||
|
min = Long.MAX_VALUE;
|
||||||
|
max = -1;
|
||||||
|
mean = 0;
|
||||||
|
for (long f: times) {
|
||||||
|
mean += f;
|
||||||
|
if (f < min) {
|
||||||
|
min = f;
|
||||||
|
}
|
||||||
|
if (f > max) {
|
||||||
|
max = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mean /= times.size();
|
||||||
|
|
||||||
|
variance = 0;
|
||||||
|
for (long f: times) {
|
||||||
|
variance += (f-mean)*(f-mean);
|
||||||
|
}
|
||||||
|
variance /= times.size();
|
||||||
|
stddev = (long) Math.sqrt((double) variance);
|
||||||
|
|
||||||
|
p10 = times.get(times.size()*10/100);
|
||||||
|
p50 = times.get(times.size()*50/100);
|
||||||
|
p90 = times.get(times.size()*90/100);
|
||||||
|
|
||||||
|
statsFresh = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
computeStats();
|
||||||
|
return String.format(
|
||||||
|
"%s:\n" +
|
||||||
|
"| %d samples\n" +
|
||||||
|
"| Mean %.3f\u00B1%.3fms\n" + // plusminus
|
||||||
|
"| Min %.3fms ; Max %.3fms\n" +
|
||||||
|
"| p10 %.3fms ; p50 %.3fms ; p90 %.3fms\n" +
|
||||||
|
"%s",
|
||||||
|
name,
|
||||||
|
times.size(),
|
||||||
|
mean/10e6,
|
||||||
|
stddev/10e6,
|
||||||
|
min/10e6,
|
||||||
|
max/10e6,
|
||||||
|
p10/10e6,
|
||||||
|
p50/10e6,
|
||||||
|
p90/10e6,
|
||||||
|
makeGraph());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String makeGraph() {
|
||||||
|
char canvas[][] = new char[GRAPH_HEIGHT][GRAPH_WIDTH];
|
||||||
|
for (int i = 0; i < GRAPH_HEIGHT; i++)
|
||||||
|
for (int j = 0; j < GRAPH_WIDTH; j++)
|
||||||
|
canvas[i][j] = ' ';
|
||||||
|
|
||||||
|
long bucketSize = (p90 - p10) / GRAPH_WIDTH+1;
|
||||||
|
int bucketCount[] = new int[GRAPH_WIDTH];
|
||||||
|
for (long time : times) {
|
||||||
|
if (time<p90 && time>p10) {
|
||||||
|
bucketCount[(int) ((time - p10) / bucketSize)]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxBucket = 0;
|
||||||
|
for (int i = 0; i < GRAPH_WIDTH; i++)
|
||||||
|
if (bucketCount[i] > maxBucket) {
|
||||||
|
maxBucket = bucketCount[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < GRAPH_HEIGHT; i++)
|
||||||
|
for (int j = 0; j < GRAPH_WIDTH; j++)
|
||||||
|
if (i < bucketCount[j] * GRAPH_HEIGHT / maxBucket) {
|
||||||
|
canvas[i][j] = 'Z';
|
||||||
|
}
|
||||||
|
|
||||||
|
String graph = new String();
|
||||||
|
for (int i = 0; i < GRAPH_HEIGHT; i++)
|
||||||
|
{
|
||||||
|
int percentage = 100 * (GRAPH_HEIGHT - i - 1) * maxBucket / (times.size() * GRAPH_HEIGHT);
|
||||||
|
graph += String.format("| %2d%% ", percentage);
|
||||||
|
for (int j = 0; j < GRAPH_WIDTH; j++)
|
||||||
|
graph += canvas[GRAPH_HEIGHT-1-i][j];
|
||||||
|
graph += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
graph += "| p10";
|
||||||
|
for (int i = 0; i < GRAPH_WIDTH-6; i++)
|
||||||
|
graph += " ";
|
||||||
|
graph += "p90\n";
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dumps the collected times to a file on the device. This allows us to grab the raw data
|
||||||
|
* and perform more in-depth analysis.
|
||||||
|
*/
|
||||||
|
public void dump(Context context) {
|
||||||
|
String state = Environment.getExternalStorageState();
|
||||||
|
if (!Environment.MEDIA_MOUNTED.equals(state)) {
|
||||||
|
Log.e("YogaLayoutBenchmark","No external file storage");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
String filename = format.format(new Date()) + "_" + name.replace(' ','_');
|
||||||
|
File file = new File(context.getExternalFilesDir(
|
||||||
|
Environment.DIRECTORY_DOCUMENTS), filename);
|
||||||
|
|
||||||
|
try {
|
||||||
|
PrintWriter printWriter = new PrintWriter(file);
|
||||||
|
for (long l : times) {
|
||||||
|
printWriter.println(l);
|
||||||
|
}
|
||||||
|
printWriter.close();
|
||||||
|
|
||||||
|
Log.i("YogaLayoutBenchmark","Benchmark data saved in "+file.getPath());
|
||||||
|
} catch (java.io.IOException e) {
|
||||||
|
Log.e("YogaLayoutBenchmark", "Could not save benchmark data", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,110 @@
|
|||||||
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewParent;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
import com.facebook.yoga.android.YogaLayout;
|
||||||
|
|
||||||
|
public class BenchmarkFragment extends Fragment implements AdapterView.OnItemSelectedListener {
|
||||||
|
private LayoutInflater mInflater;
|
||||||
|
|
||||||
|
protected com.facebook.yoga.android.YogaLayout rootLayout;
|
||||||
|
protected int yogaLayout;
|
||||||
|
protected int linearLayout;
|
||||||
|
|
||||||
|
static final Random random = new Random();
|
||||||
|
|
||||||
|
static void randomizeText(View root) {
|
||||||
|
if (root instanceof TextView) {
|
||||||
|
((TextView) root).setText("" + random.nextInt(1000));
|
||||||
|
((TextView) root).setTextSize(10 + random.nextInt(20));
|
||||||
|
ViewParent parent = root.getParent();
|
||||||
|
if (parent instanceof YogaLayout) {
|
||||||
|
((YogaLayout) parent).invalidate(root);
|
||||||
|
}
|
||||||
|
} else if (root instanceof ViewGroup) {
|
||||||
|
for (int i = 0; i < ((ViewGroup) root).getChildCount(); i++) {
|
||||||
|
randomizeText(((ViewGroup) root).getChildAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BenchmarkFragment() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(
|
||||||
|
LayoutInflater inflater,
|
||||||
|
ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
mInflater = inflater;
|
||||||
|
|
||||||
|
rootLayout = (YogaLayout) inflater.inflate(
|
||||||
|
R.layout.benchmark_fragment,
|
||||||
|
container,
|
||||||
|
false);
|
||||||
|
|
||||||
|
Spinner benchmarkSelect = (Spinner) rootLayout.findViewById(R.id.benchmarkSelect);
|
||||||
|
String[] items = new String[]{"Basic", "Typical", "Nested"};
|
||||||
|
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_dropdown_item, items);
|
||||||
|
benchmarkSelect.setAdapter(adapter);
|
||||||
|
benchmarkSelect.setOnItemSelectedListener(this);
|
||||||
|
return rootLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
|
||||||
|
switch (pos) {
|
||||||
|
case 0:
|
||||||
|
yogaLayout = R.layout.benchmark_layout_1;
|
||||||
|
linearLayout = R.layout.benchmark_layout_1_linear;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
yogaLayout = R.layout.benchmark_layout_2;
|
||||||
|
linearLayout = R.layout.benchmark_layout_2_linear;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
yogaLayout = R.layout.benchmark_layout_3;
|
||||||
|
linearLayout = R.layout.benchmark_layout_3_linear;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
updatePreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
yogaLayout = R.layout.benchmark_layout_1;
|
||||||
|
linearLayout = R.layout.benchmark_layout_1_linear;
|
||||||
|
updatePreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePreview() {
|
||||||
|
LinearLayout previewLayout = (LinearLayout) rootLayout.findViewById(R.id.preview);
|
||||||
|
View v = mInflater.inflate(yogaLayout, rootLayout, false);
|
||||||
|
v.setLayoutParams(new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT));
|
||||||
|
previewLayout.removeAllViews();
|
||||||
|
previewLayout.addView(v);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,65 @@
|
|||||||
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.util.Log;
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
|
||||||
|
public class BenchmarkInflate extends BenchmarkFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(
|
||||||
|
LayoutInflater inflater,
|
||||||
|
ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
|
||||||
|
Button b = (Button) rootLayout.findViewById(R.id.btn);
|
||||||
|
b.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
startBenchmark();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rootLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startBenchmark() {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||||
|
TextView textView = (TextView) rootLayout.findViewById(R.id.text);
|
||||||
|
|
||||||
|
final int ITERATIONS = 500;
|
||||||
|
|
||||||
|
inflater.inflate(yogaLayout, null);
|
||||||
|
inflater.inflate(linearLayout, null);
|
||||||
|
|
||||||
|
BenchmarkAggregator yogaInflationAggregator = new BenchmarkAggregator("Yoga Inflate");
|
||||||
|
BenchmarkAggregator linearInflationAggregator = new BenchmarkAggregator("Linear Inflate");
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
yogaInflationAggregator.startTrace();
|
||||||
|
inflater.inflate(yogaLayout, null);
|
||||||
|
yogaInflationAggregator.endTrace();
|
||||||
|
linearInflationAggregator.startTrace();
|
||||||
|
inflater.inflate(linearLayout, null);
|
||||||
|
linearInflationAggregator.endTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
textView.setText(
|
||||||
|
yogaInflationAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearInflationAggregator.toString());
|
||||||
|
Log.i(
|
||||||
|
"YogaLayoutBenchmark",
|
||||||
|
yogaInflationAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearInflationAggregator.toString());
|
||||||
|
rootLayout.invalidate();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BenchmarkLayout extends BenchmarkFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(
|
||||||
|
LayoutInflater inflater,
|
||||||
|
ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
|
||||||
|
Button b = (Button) rootLayout.findViewById(R.id.btn);
|
||||||
|
b.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
startBenchmark();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rootLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startBenchmark() {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||||
|
TextView textView = (TextView) rootLayout.findViewById(R.id.text);
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
final int ITERATIONS = 500;
|
||||||
|
|
||||||
|
BenchmarkAggregator yogaInflationAggregator = new BenchmarkAggregator("Yoga Layout");
|
||||||
|
BenchmarkAggregator linearInflationAggregator = new BenchmarkAggregator("Linear Layout");
|
||||||
|
View yogaView = inflater.inflate(yogaLayout, null);
|
||||||
|
View linearView = inflater.inflate(linearLayout, null);
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
randomizeText(yogaView);
|
||||||
|
randomizeText(linearView);
|
||||||
|
yogaView.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY));
|
||||||
|
linearView.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY));
|
||||||
|
yogaInflationAggregator.startTrace();
|
||||||
|
yogaView.layout(0, 0, yogaView.getMeasuredWidth(), yogaView.getMeasuredHeight());
|
||||||
|
yogaInflationAggregator.endTrace();
|
||||||
|
linearInflationAggregator.startTrace();
|
||||||
|
linearView.layout(0, 0, linearView.getMeasuredWidth(), linearView.getMeasuredHeight());
|
||||||
|
linearInflationAggregator.endTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
textView.setText(
|
||||||
|
yogaInflationAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearInflationAggregator.toString());
|
||||||
|
Log.i(
|
||||||
|
"YogaLayoutBenchmark",
|
||||||
|
yogaInflationAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearInflationAggregator.toString());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.facebook.samples.yoga;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BenchmarkMeasure extends BenchmarkFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(
|
||||||
|
LayoutInflater inflater,
|
||||||
|
ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
|
||||||
|
Button b = (Button) rootLayout.findViewById(R.id.btn);
|
||||||
|
b.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
startBenchmark();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rootLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startBenchmark() {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||||
|
TextView textView = (TextView) rootLayout.findViewById(R.id.text);
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
final int ITERATIONS = 500;
|
||||||
|
|
||||||
|
BenchmarkAggregator yogaMeasureAggregator = new BenchmarkAggregator("Yoga Measure");
|
||||||
|
BenchmarkAggregator linearMeasureAggregator = new BenchmarkAggregator("Linear Measure");
|
||||||
|
View yogaView = inflater.inflate(yogaLayout, null);
|
||||||
|
View linearView = inflater.inflate(linearLayout, null);
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
randomizeText(yogaView);
|
||||||
|
randomizeText(linearView);
|
||||||
|
yogaMeasureAggregator.startTrace();
|
||||||
|
yogaView.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY));
|
||||||
|
yogaMeasureAggregator.endTrace();
|
||||||
|
linearMeasureAggregator.startTrace();
|
||||||
|
linearView.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY));
|
||||||
|
linearMeasureAggregator.endTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
textView.setText(
|
||||||
|
yogaMeasureAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearMeasureAggregator.toString());
|
||||||
|
Log.i(
|
||||||
|
"YogaLayoutBenchmark",
|
||||||
|
yogaMeasureAggregator.toString()+
|
||||||
|
"\n"+
|
||||||
|
linearMeasureAggregator.toString());
|
||||||
|
|
||||||
|
yogaMeasureAggregator.dump(getActivity());
|
||||||
|
linearMeasureAggregator.dump(getActivity());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* 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.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.Menu;
|
||||||
|
|
||||||
|
import com.facebook.samples.yoga.R;
|
||||||
|
import com.facebook.soloader.SoLoader;
|
||||||
|
import com.facebook.yoga.android.YogaViewLayoutFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An activity to show off Yoga in Android. This activity shows a simple layout (defined in
|
||||||
|
* {@code main_layout.xml}) that shows off the awesome functionality of the Yoga layout engine
|
||||||
|
* as well as some optimisations on layout systems that it facilitates.
|
||||||
|
*/
|
||||||
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
LayoutInflater.from(this).setFactory(YogaViewLayoutFactory.getInstance());
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
SoLoader.init(this, false);
|
||||||
|
|
||||||
|
setContentView(R.layout.main_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.action_bar_home, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
// There is only one option
|
||||||
|
Intent intent = new Intent(this, BenchmarkActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
this.finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
17
android/sample/res/drawable/action_bar_background.xml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2014-present, Facebook, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This source code is licensed under the license found in the
|
||||||
|
LICENSE-examples file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle"
|
||||||
|
>
|
||||||
|
<solid
|
||||||
|
android:color="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
</shape>
|
BIN
android/sample/res/drawable/ic_launcher.png
Normal file
After Width: | Height: | Size: 28 KiB |
34
android/sample/res/drawable/sample_children_background.xml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2014-present, Facebook, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This source code is licensed under the license found in the
|
||||||
|
LICENSE-examples file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle"
|
||||||
|
>
|
||||||
|
|
||||||
|
<corners
|
||||||
|
android:radius="4dp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="@color/children_stroke"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<padding
|
||||||
|
android:top="6dp"
|
||||||
|
android:bottom="6dp"
|
||||||
|
android:left="8dp"
|
||||||
|
android:right="8dp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<solid
|
||||||
|
android:color="@color/children_background"
|
||||||
|
/>
|
||||||
|
</shape>
|
50
android/sample/res/layout/benchmark_fragment.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<YogaLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:yoga="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/rt"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_height="50dp"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="Run benchmark"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/benchmarkSelect"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:spinnerMode="dropdown"
|
||||||
|
/>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="2dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/preview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
30
android/sample/res/layout/benchmark_layout_1.xml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<YogaLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:yoga="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_flex="0"
|
||||||
|
yoga:yg_marginAll="5dp"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
yoga:yg_flex="0"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_2_text"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
yoga:yg_marginHorizontal="5dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
28
android/sample/res/layout/benchmark_layout_1_linear.xml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
android:layout_marginRight="5dp"
|
||||||
|
android:text="@string/child_2_text"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
104
android/sample/res/layout/benchmark_layout_2.xml
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<YogaLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:yoga="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:height="40dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginAll="10dp"
|
||||||
|
yoga:yg_aspectRatio="1"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:height="40dp"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
yoga:yg_justifyContent="space_around"
|
||||||
|
>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:height="8dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_aspectRatio="1"
|
||||||
|
/>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:height="8dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_aspectRatio="1"
|
||||||
|
/>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:height="8dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="stretch"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_aspectRatio="1"
|
||||||
|
/>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</YogaLayout>
|
96
android/sample/res/layout/benchmark_layout_2_linear.xml
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:yoga="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="8dp"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="8dp"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textSize="5sp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
android:layout_width="8dp"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
206
android/sample/res/layout/benchmark_layout_3.xml
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<YogaLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:yoga="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_justifyContent="center"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="column"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
yoga:yg_marginLeft="10dp"
|
||||||
|
/>
|
||||||
|
<VirtualYogaLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</VirtualYogaLayout>
|
||||||
|
</YogaLayout>
|
204
android/sample/res/layout/benchmark_layout_3_linear.xml
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_blue"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:background="@color/yoga_grey"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
7
android/sample/res/layout/benchmark_select_layout.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<android.support.v4.view.ViewPager
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/viewpager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
/>
|
137
android/sample/res/layout/main_layout.xml
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2014-present, Facebook, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This source code is licensed under the license found in the
|
||||||
|
LICENSE-examples file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<YogaLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:yoga="http://schemas.android.com/apk/res/com.facebook.samples.yoga"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
>
|
||||||
|
<YogaLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/sample_children_background"
|
||||||
|
yoga:yg_marginHorizontal="10dp"
|
||||||
|
yoga:yg_marginTop="5dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
yoga:yg_flex="0"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_1_text"
|
||||||
|
android:textColor="@color/children_text"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
yoga:yg_marginStart="8dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
||||||
|
<YogaLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/sample_children_background"
|
||||||
|
yoga:yg_marginHorizontal="10dp"
|
||||||
|
yoga:yg_marginTop="5dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
yoga:yg_flex="0"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_2_text"
|
||||||
|
android:textColor="@color/children_text"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
yoga:yg_marginStart="8dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
||||||
|
<YogaLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/sample_children_background"
|
||||||
|
yoga:yg_marginHorizontal="10dp"
|
||||||
|
yoga:yg_marginTop="5dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
yoga:yg_flex="0"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_3_text"
|
||||||
|
android:textColor="@color/children_text"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
yoga:yg_marginStart="8dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
||||||
|
<YogaLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/sample_children_background"
|
||||||
|
yoga:yg_marginHorizontal="10dp"
|
||||||
|
yoga:yg_marginTop="5dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
yoga:yg_flex="0"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_4_text"
|
||||||
|
android:textColor="@color/children_text"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
yoga:yg_marginStart="8dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
||||||
|
<YogaLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/sample_children_background"
|
||||||
|
yoga:yg_marginHorizontal="10dp"
|
||||||
|
yoga:yg_marginTop="5dp"
|
||||||
|
yoga:yg_flexDirection="row"
|
||||||
|
yoga:yg_alignItems="center"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:src="@drawable/ic_launcher"
|
||||||
|
yoga:yg_flex="0"
|
||||||
|
/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/child_5_text"
|
||||||
|
android:textColor="@color/children_text"
|
||||||
|
yoga:yg_flex="1"
|
||||||
|
yoga:yg_marginStart="10dp"
|
||||||
|
/>
|
||||||
|
</YogaLayout>
|
||||||
|
</YogaLayout>
|
19
android/sample/res/menu/action_bar_benchmark.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2014-present, Facebook, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This source code is licensed under the license found in the
|
||||||
|
LICENSE-examples file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
>
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_home"
|
||||||
|
android:title="Home"
|
||||||
|
android:showAsAction="always"
|
||||||
|
/>
|
||||||
|
</menu>
|
19
android/sample/res/menu/action_bar_home.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2014-present, Facebook, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This source code is licensed under the license found in the
|
||||||
|
LICENSE-examples file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
>
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_benchmark"
|
||||||
|
android:title="Benchmark"
|
||||||
|
android:showAsAction="always"
|
||||||
|
/>
|
||||||
|
</menu>
|
20
android/sample/res/values/colors.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2014-present, Facebook, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This source code is licensed under the license found in the
|
||||||
|
LICENSE-examples file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<color name="yoga_grey">#FF303846</color>
|
||||||
|
<color name="yoga_blue">#FF97DCCF</color>
|
||||||
|
|
||||||
|
<color name="children_background">#FFFFFFFF</color>
|
||||||
|
<color name="children_stroke">#665890ff</color>
|
||||||
|
<color name="children_text">#FF23355b</color>
|
||||||
|
|
||||||
|
</resources>
|
33
android/sample/res/values/strings.xml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2014-present, Facebook, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This source code is licensed under the license found in the
|
||||||
|
LICENSE-examples file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">Yoga</string>
|
||||||
|
<string
|
||||||
|
name="child_1_text"
|
||||||
|
description="Placeholder text for the first element in the layout"
|
||||||
|
>Hello. I am Yoga!</string>
|
||||||
|
<string
|
||||||
|
name="child_2_text"
|
||||||
|
description="Placeholder text for the second element in the layout"
|
||||||
|
>I am a layout engine!</string>
|
||||||
|
<string
|
||||||
|
name="child_3_text"
|
||||||
|
description="Placeholder text for the third element in the layout"
|
||||||
|
>I run natively.</string>
|
||||||
|
<string
|
||||||
|
name="child_4_text"
|
||||||
|
description="Placeholder text for the fourth element in the layout"
|
||||||
|
>So I\'m fast.</string>
|
||||||
|
<string
|
||||||
|
name="child_5_text"
|
||||||
|
description="Placeholder text for the fifth element in the layout"
|
||||||
|
>Who are you?</string>
|
||||||
|
</resources>
|
23
android/sample/res/values/styles.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2014-present, Facebook, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This source code is licensed under the license found in the
|
||||||
|
LICENSE-examples file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<style name="NoTitleBarWhiteBG" parent="Theme.AppCompat.Light">
|
||||||
|
<item name="android:actionBarStyle">@style/MyActionBar</item>
|
||||||
|
<item name="android:textDirection">locale</item>
|
||||||
|
</style>
|
||||||
|
<style name="MyActionBar" parent="Widget.AppCompat.Light.ActionBar">
|
||||||
|
<item name="android:titleTextStyle">@style/MyTitleText</item>
|
||||||
|
<item name="android:background">@drawable/action_bar_background</item>
|
||||||
|
</style>
|
||||||
|
<style name="MyTitleText" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
|
||||||
|
<item name="android:textColor">@color/yoga_blue</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
23
android/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
|
||||||
|
This source code is licensed under the MIT license found in the
|
||||||
|
LICENSE file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.facebook.yoga.android"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0"
|
||||||
|
>
|
||||||
|
|
||||||
|
<uses-sdk
|
||||||
|
android:minSdkVersion="15"
|
||||||
|
android:targetSdkVersion="21"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<application/>
|
||||||
|
|
||||||
|
</manifest>
|
21
android/src/main/java/com/facebook/yoga/android/BUCK
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
#
|
||||||
|
# This source code is licensed under the MIT license found in the
|
||||||
|
# LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_RES_TARGET", "INFER_ANNOTATIONS_TARGET", "JAVA_TARGET", "JSR_305_TARGET", "SOLOADER_TARGET", "yoga_android_library")
|
||||||
|
|
||||||
|
yoga_android_library(
|
||||||
|
name = "android",
|
||||||
|
srcs = glob(["**/*.java"]),
|
||||||
|
visibility = [
|
||||||
|
"PUBLIC",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
ANDROID_RES_TARGET,
|
||||||
|
INFER_ANNOTATIONS_TARGET,
|
||||||
|
JAVA_TARGET,
|
||||||
|
JSR_305_TARGET,
|
||||||
|
SOLOADER_TARGET,
|
||||||
|
],
|
||||||
|
)
|
@@ -0,0 +1,148 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.yoga.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 = YogaNode.create();
|
||||||
|
|
||||||
|
public VirtualYogaLayout(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualYogaLayout(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualYogaLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
YogaLayout.LayoutParams lp = new YogaLayout.LayoutParams(context, attrs);
|
||||||
|
YogaLayout.applyLayoutParams(lp, mYogaNode, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public YogaNode getYogaNode() {
|
||||||
|
return mYogaNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to add a view, creating a new yoga node for it and adding that yoga node to the parent.
|
||||||
|
* If the child is a {@link VirtualYogaLayout}, we simply transfer all its children to this one
|
||||||
|
* in a manner that maintains the tree, and add its root to the tree.
|
||||||
|
*
|
||||||
|
* @param child the View to add
|
||||||
|
* @param index the position at which to add it (ignored)
|
||||||
|
* @param params the layout parameters to apply
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void addView(View child, int index, ViewGroup.LayoutParams params) {
|
||||||
|
if (child instanceof VirtualYogaLayout) {
|
||||||
|
((VirtualYogaLayout) child).transferChildren(this);
|
||||||
|
|
||||||
|
final YogaNode childNode = ((VirtualYogaLayout) child).getYogaNode();
|
||||||
|
mYogaNode.addChildAt(childNode, mYogaNode.getChildCount());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
YogaNode node = YogaNode.create();
|
||||||
|
YogaLayout.LayoutParams lp = new YogaLayout.LayoutParams(params);
|
||||||
|
YogaLayout.applyLayoutParams(lp, node, child);
|
||||||
|
node.setData(child);
|
||||||
|
node.setMeasureFunction(new YogaLayout.ViewMeasureFunction());
|
||||||
|
|
||||||
|
mYogaNode.addChildAt(node, mYogaNode.getChildCount());
|
||||||
|
|
||||||
|
addView(child, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to add a view with a corresponding node, but not to change the Yoga tree in any way.
|
||||||
|
*
|
||||||
|
* @param child the View to add
|
||||||
|
* @param node the corresponding yoga node
|
||||||
|
*/
|
||||||
|
public void addView(View child, YogaNode node) {
|
||||||
|
mChildren.add(child);
|
||||||
|
mYogaNodes.put(child, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives up children {@code View}s to the parent, maintaining the Yoga tree. This function calls
|
||||||
|
* {@link YogaLayout#addView(View, YogaNode)} or {@link VirtualYogaLayout#addView(View, YogaNode)}
|
||||||
|
* on the parent to add the {@code View} without generating new yoga nodes.
|
||||||
|
*
|
||||||
|
* @param parent the parent to pass children to (must be a YogaLayout or a VirtualYogaLayout)
|
||||||
|
*/
|
||||||
|
protected void transferChildren(ViewGroup parent) {
|
||||||
|
if (parent instanceof VirtualYogaLayout) {
|
||||||
|
for (View child : mChildren) {
|
||||||
|
((VirtualYogaLayout) parent).addView(child, mYogaNodes.get(child));
|
||||||
|
}
|
||||||
|
} else if (parent instanceof YogaLayout) {
|
||||||
|
for (View child : mChildren) {
|
||||||
|
((YogaLayout) parent).addView(child, mYogaNodes.get(child));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("VirtualYogaLayout cannot transfer children to ViewGroup of type "
|
||||||
|
+parent.getClass().getCanonicalName()+". Must either be a VirtualYogaLayout or a " +
|
||||||
|
"YogaLayout.");
|
||||||
|
}
|
||||||
|
mChildren.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||||
|
throw new RuntimeException("Attempting to layout a VirtualYogaLayout");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
|
||||||
|
return new YogaLayout.LayoutParams(getContext(), attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
|
||||||
|
return new YogaLayout.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
|
||||||
|
return new YogaLayout.LayoutParams(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
|
||||||
|
return p instanceof YogaLayout.LayoutParams;
|
||||||
|
}
|
||||||
|
}
|
815
android/src/main/java/com/facebook/yoga/android/YogaLayout.java
Normal file
@@ -0,0 +1,815 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.yoga.android;
|
||||||
|
|
||||||
|
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.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.YogaOverflow;
|
||||||
|
import com.facebook.yoga.YogaPositionType;
|
||||||
|
import com.facebook.yoga.YogaWrap;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code ViewGroup} based on the Yoga layout engine.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This class is designed to be as "plug and play" as possible. That is, you can use it in XML
|
||||||
|
* like this (note: to use {@code YogaLayout} you need to use the {@link YogaViewLayoutFactory}):
|
||||||
|
* <p>
|
||||||
|
* <pre>{@code
|
||||||
|
* <YogaLayout
|
||||||
|
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
* xmlns:yoga="http://schemas.android.com/apk/com.facebook.yoga.android"
|
||||||
|
* android:layout_width="match_owner"
|
||||||
|
* android:layout_height="match_owner"
|
||||||
|
* yoga:flex_direction="row"
|
||||||
|
* yoga:padding_all="10dp"
|
||||||
|
* >
|
||||||
|
* <TextView
|
||||||
|
* android:layout_width="match_owner"
|
||||||
|
* android:layout_height="match_owner"
|
||||||
|
* 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 = YogaNode.create();
|
||||||
|
mYogaNodes = new HashMap<>();
|
||||||
|
|
||||||
|
mYogaNode.setData(this);
|
||||||
|
mYogaNode.setMeasureFunction(new ViewMeasureFunction());
|
||||||
|
|
||||||
|
LayoutParams layoutParams = null;
|
||||||
|
if (attrs != null) {
|
||||||
|
layoutParams = new LayoutParams(context, attrs);
|
||||||
|
} else {
|
||||||
|
layoutParams = (LayoutParams) generateDefaultLayoutParams();
|
||||||
|
}
|
||||||
|
applyLayoutParams(layoutParams, mYogaNode, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public YogaNode getYogaNode() {
|
||||||
|
return mYogaNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public 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 {
|
||||||
|
if(mYogaNodes.containsKey(child)) {
|
||||||
|
childNode = mYogaNodes.get(child);
|
||||||
|
} else {
|
||||||
|
childNode = YogaNode.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 owner = node.getOwner();
|
||||||
|
|
||||||
|
for (int i = 0; i < owner.getChildCount(); i++) {
|
||||||
|
if (owner.getChildAt(i).equals(node)) {
|
||||||
|
owner.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;
|
||||||
|
}
|
||||||
|
int left = Math.round(xOffset + node.getLayoutX());
|
||||||
|
int top = Math.round(yOffset + node.getLayoutY());
|
||||||
|
view.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(
|
||||||
|
Math.round(node.getLayoutWidth()),
|
||||||
|
View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(
|
||||||
|
Math.round(node.getLayoutHeight()),
|
||||||
|
View.MeasureSpec.EXACTLY));
|
||||||
|
view.layout(left, top, left + view.getMeasuredWidth(), top + view.getMeasuredHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
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 owner'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_alignContent) {
|
||||||
|
node.setAlignContent(YogaAlign.fromInt(Math.round(value)));
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_alignItems) {
|
||||||
|
node.setAlignItems(YogaAlign.fromInt(Math.round(value)));
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_alignSelf) {
|
||||||
|
node.setAlignSelf(YogaAlign.fromInt(Math.round(value)));
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_aspectRatio) {
|
||||||
|
node.setAspectRatio(value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_borderLeft) {
|
||||||
|
node.setBorder(YogaEdge.LEFT, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_borderTop) {
|
||||||
|
node.setBorder(YogaEdge.TOP, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_borderRight) {
|
||||||
|
node.setBorder(YogaEdge.RIGHT, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_borderBottom) {
|
||||||
|
node.setBorder(YogaEdge.BOTTOM, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_borderStart) {
|
||||||
|
node.setBorder(YogaEdge.START, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_borderEnd) {
|
||||||
|
node.setBorder(YogaEdge.END, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_borderHorizontal) {
|
||||||
|
node.setBorder(YogaEdge.HORIZONTAL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_borderVertical) {
|
||||||
|
node.setBorder(YogaEdge.VERTICAL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_borderAll) {
|
||||||
|
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_flexBasis) {
|
||||||
|
node.setFlexBasis(value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_flexDirection) {
|
||||||
|
node.setFlexDirection(YogaFlexDirection.fromInt(Math.round(value)));
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_flexGrow) {
|
||||||
|
node.setFlexGrow(value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_flexShrink) {
|
||||||
|
node.setFlexShrink(value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_height) {
|
||||||
|
node.setHeight(value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginLeft) {
|
||||||
|
node.setMargin(YogaEdge.LEFT, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_justifyContent) {
|
||||||
|
node.setJustifyContent(YogaJustify.fromInt(Math.round(value)));
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginTop) {
|
||||||
|
node.setMargin(YogaEdge.TOP, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginRight) {
|
||||||
|
node.setMargin(YogaEdge.RIGHT, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginBottom) {
|
||||||
|
node.setMargin(YogaEdge.BOTTOM, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginStart) {
|
||||||
|
node.setMargin(YogaEdge.START, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginEnd) {
|
||||||
|
node.setMargin(YogaEdge.END, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginHorizontal) {
|
||||||
|
node.setMargin(YogaEdge.HORIZONTAL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginVertical) {
|
||||||
|
node.setMargin(YogaEdge.VERTICAL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginAll) {
|
||||||
|
node.setMargin(YogaEdge.ALL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_maxHeight) {
|
||||||
|
node.setMaxHeight(value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_maxWidth) {
|
||||||
|
node.setMaxWidth(value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_minHeight) {
|
||||||
|
node.setMinHeight(value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_minWidth) {
|
||||||
|
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_paddingLeft) {
|
||||||
|
node.setPadding(YogaEdge.LEFT, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingTop) {
|
||||||
|
node.setPadding(YogaEdge.TOP, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingRight) {
|
||||||
|
node.setPadding(YogaEdge.RIGHT, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingBottom) {
|
||||||
|
node.setPadding(YogaEdge.BOTTOM, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingStart) {
|
||||||
|
node.setPadding(YogaEdge.START, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingEnd) {
|
||||||
|
node.setPadding(YogaEdge.END, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingHorizontal) {
|
||||||
|
node.setPadding(YogaEdge.HORIZONTAL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingVertical) {
|
||||||
|
node.setPadding(YogaEdge.VERTICAL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingAll) {
|
||||||
|
node.setPadding(YogaEdge.ALL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionLeft) {
|
||||||
|
node.setPosition(YogaEdge.LEFT, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionTop) {
|
||||||
|
node.setPosition(YogaEdge.TOP, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionRight) {
|
||||||
|
node.setPosition(YogaEdge.RIGHT, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionBottom) {
|
||||||
|
node.setPosition(YogaEdge.BOTTOM, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionStart) {
|
||||||
|
node.setPosition(YogaEdge.START, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionEnd) {
|
||||||
|
node.setPosition(YogaEdge.END, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionHorizontal) {
|
||||||
|
node.setPosition(YogaEdge.HORIZONTAL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionVertical) {
|
||||||
|
node.setPosition(YogaEdge.VERTICAL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionAll) {
|
||||||
|
node.setPosition(YogaEdge.ALL, value);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionType) {
|
||||||
|
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_marginLeft) {
|
||||||
|
node.setMarginAuto(YogaEdge.LEFT);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginTop) {
|
||||||
|
node.setMarginAuto(YogaEdge.TOP);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginRight) {
|
||||||
|
node.setMarginAuto(YogaEdge.RIGHT);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginBottom) {
|
||||||
|
node.setMarginAuto(YogaEdge.BOTTOM);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginStart) {
|
||||||
|
node.setMarginAuto(YogaEdge.START);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginEnd) {
|
||||||
|
node.setMarginAuto(YogaEdge.END);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginHorizontal) {
|
||||||
|
node.setMarginAuto(YogaEdge.HORIZONTAL);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginVertical) {
|
||||||
|
node.setMarginAuto(YogaEdge.VERTICAL);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginAll) {
|
||||||
|
node.setMarginAuto(YogaEdge.ALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.endsWith("%")) {
|
||||||
|
final float numericValue = Float.parseFloat(value.substring(0, value.length()-1));
|
||||||
|
|
||||||
|
if (attribute == R.styleable.yoga_yg_flexBasis) {
|
||||||
|
node.setFlexBasisPercent(numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_height) {
|
||||||
|
node.setHeightPercent(numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginLeft) {
|
||||||
|
node.setMarginPercent(YogaEdge.LEFT, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginTop) {
|
||||||
|
node.setMarginPercent(YogaEdge.TOP, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginRight) {
|
||||||
|
node.setMarginPercent(YogaEdge.RIGHT, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginBottom) {
|
||||||
|
node.setMarginPercent(YogaEdge.BOTTOM, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginStart) {
|
||||||
|
node.setMarginPercent(YogaEdge.START, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginEnd) {
|
||||||
|
node.setMarginPercent(YogaEdge.END, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginHorizontal) {
|
||||||
|
node.setMarginPercent(YogaEdge.HORIZONTAL, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginVertical) {
|
||||||
|
node.setMarginPercent(YogaEdge.VERTICAL, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_marginAll) {
|
||||||
|
node.setMarginPercent(YogaEdge.ALL, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_maxHeight) {
|
||||||
|
node.setMaxHeightPercent(numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_maxWidth) {
|
||||||
|
node.setMaxWidthPercent(numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_minHeight) {
|
||||||
|
node.setMinHeightPercent(numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_minWidth) {
|
||||||
|
node.setMinWidthPercent(numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingLeft) {
|
||||||
|
node.setPaddingPercent(YogaEdge.LEFT, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingTop) {
|
||||||
|
node.setPaddingPercent(YogaEdge.TOP, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingRight) {
|
||||||
|
node.setPaddingPercent(YogaEdge.RIGHT, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingBottom) {
|
||||||
|
node.setPaddingPercent(YogaEdge.BOTTOM, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingStart) {
|
||||||
|
node.setPaddingPercent(YogaEdge.START, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingEnd) {
|
||||||
|
node.setPaddingPercent(YogaEdge.END, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingHorizontal) {
|
||||||
|
node.setPaddingPercent(YogaEdge.HORIZONTAL, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingVertical) {
|
||||||
|
node.setPaddingPercent(YogaEdge.VERTICAL, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_paddingAll) {
|
||||||
|
node.setPaddingPercent(YogaEdge.ALL, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionLeft) {
|
||||||
|
node.setPositionPercent(YogaEdge.LEFT, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionTop) {
|
||||||
|
node.setPositionPercent(YogaEdge.TOP, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionRight) {
|
||||||
|
node.setPositionPercent(YogaEdge.RIGHT, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionBottom) {
|
||||||
|
node.setPositionPercent(YogaEdge.BOTTOM, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionStart) {
|
||||||
|
node.setPositionPercent(YogaEdge.START, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionEnd) {
|
||||||
|
node.setPositionPercent(YogaEdge.END, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionHorizontal) {
|
||||||
|
node.setPositionPercent(YogaEdge.HORIZONTAL, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionVertical) {
|
||||||
|
node.setPositionPercent(YogaEdge.VERTICAL, numericValue);
|
||||||
|
} else if (attribute == R.styleable.yoga_yg_positionAll) {
|
||||||
|
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_owner} or {@code wrap_content} are given, then the owner
|
||||||
|
* 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 owner
|
||||||
|
* @param widthMode The type of suggestion for the width
|
||||||
|
* @param height The suggested height from the owner
|
||||||
|
* @param heightMode The type of suggestion for the height
|
||||||
|
* @return A measurement output ({@code YogaMeasureOutput}) for the node
|
||||||
|
*/
|
||||||
|
public long measure(
|
||||||
|
YogaNode 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|