yoga-layout-python 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yoga/YGConfig.py +92 -0
- yoga/YGEnums.py +404 -0
- yoga/YGMacros.py +9 -0
- yoga/YGNode.py +367 -0
- yoga/YGNodeLayout.py +81 -0
- yoga/YGNodeStyle.py +876 -0
- yoga/YGPixelGrid.py +42 -0
- yoga/YGValue.py +49 -0
- yoga/__init__.py +16 -0
- yoga/algorithm/AbsoluteLayout.py +417 -0
- yoga/algorithm/Align.py +34 -0
- yoga/algorithm/Baseline.py +54 -0
- yoga/algorithm/BoundAxis.py +55 -0
- yoga/algorithm/Cache.py +93 -0
- yoga/algorithm/CalculateLayout.py +1651 -0
- yoga/algorithm/FlexDirection.py +76 -0
- yoga/algorithm/FlexLine.py +130 -0
- yoga/algorithm/PixelGrid.py +56 -0
- yoga/algorithm/SizingMode.py +39 -0
- yoga/algorithm/TrailingPosition.py +34 -0
- yoga/algorithm/__init__.py +18 -0
- yoga/config/Config.py +137 -0
- yoga/config/__init__.py +9 -0
- yoga/debug/AssertFatal.py +24 -0
- yoga/debug/Log.py +49 -0
- yoga/debug/__init__.py +10 -0
- yoga/event/__init__.py +9 -0
- yoga/event/event.py +123 -0
- yoga/node/CachedMeasurement.py +51 -0
- yoga/node/LayoutResults.py +225 -0
- yoga/node/LayoutableChildren.py +79 -0
- yoga/node/Node.py +566 -0
- yoga/node/__init__.py +11 -0
- yoga/numeric/Comparison.py +46 -0
- yoga/numeric/FloatMath.py +24 -0
- yoga/numeric/FloatOptional.py +65 -0
- yoga/numeric/__init__.py +10 -0
- yoga/style/GridLine.py +44 -0
- yoga/style/GridTrack.py +47 -0
- yoga/style/SmallValueBuffer.py +133 -0
- yoga/style/Style.py +763 -0
- yoga/style/StyleLength.py +88 -0
- yoga/style/StyleSizeLength.py +117 -0
- yoga/style/StyleValueHandle.py +98 -0
- yoga/style/StyleValuePool.py +191 -0
- yoga/style/__init__.py +16 -0
- yoga_layout_python-0.1.0.dist-info/METADATA +158 -0
- yoga_layout_python-0.1.0.dist-info/RECORD +51 -0
- yoga_layout_python-0.1.0.dist-info/WHEEL +5 -0
- yoga_layout_python-0.1.0.dist-info/licenses/LICENSE +21 -0
- yoga_layout_python-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
|
|
4
|
+
This source code is licensed under the MIT license found in the
|
|
5
|
+
LICENSE file in the root directory of this source tree.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from ..debug.AssertFatal import fatalWithMessage
|
|
11
|
+
from ..YGEnums import YGDimension, YGDirection, YGEdge, YGFlexDirection
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def isRow(flexDirection: YGFlexDirection) -> bool:
|
|
15
|
+
return flexDirection in (YGFlexDirection.YGFlexDirectionRow, YGFlexDirection.YGFlexDirectionRowReverse)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def isColumn(flexDirection: YGFlexDirection) -> bool:
|
|
19
|
+
return flexDirection in (YGFlexDirection.YGFlexDirectionColumn, YGFlexDirection.YGFlexDirectionColumnReverse)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def resolveDirection(flexDirection: YGFlexDirection, direction: YGDirection) -> YGFlexDirection:
|
|
23
|
+
if direction == YGDirection.YGDirectionRTL:
|
|
24
|
+
if flexDirection == YGFlexDirection.YGFlexDirectionRow:
|
|
25
|
+
return YGFlexDirection.YGFlexDirectionRowReverse
|
|
26
|
+
if flexDirection == YGFlexDirection.YGFlexDirectionRowReverse:
|
|
27
|
+
return YGFlexDirection.YGFlexDirectionRow
|
|
28
|
+
return flexDirection
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def resolveCrossDirection(flexDirection: YGFlexDirection, direction: YGDirection) -> YGFlexDirection:
|
|
32
|
+
return resolveDirection(YGFlexDirection.YGFlexDirectionRow, direction) if isColumn(flexDirection) else YGFlexDirection.YGFlexDirectionColumn
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def flexStartEdge(flexDirection: YGFlexDirection) -> YGEdge:
|
|
36
|
+
if flexDirection == YGFlexDirection.YGFlexDirectionColumn:
|
|
37
|
+
return YGEdge.YGEdgeTop
|
|
38
|
+
if flexDirection == YGFlexDirection.YGFlexDirectionColumnReverse:
|
|
39
|
+
return YGEdge.YGEdgeBottom
|
|
40
|
+
if flexDirection == YGFlexDirection.YGFlexDirectionRow:
|
|
41
|
+
return YGEdge.YGEdgeLeft
|
|
42
|
+
if flexDirection == YGFlexDirection.YGFlexDirectionRowReverse:
|
|
43
|
+
return YGEdge.YGEdgeRight
|
|
44
|
+
fatalWithMessage("Invalid FlexDirection")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def flexEndEdge(flexDirection: YGFlexDirection) -> YGEdge:
|
|
48
|
+
if flexDirection == YGFlexDirection.YGFlexDirectionColumn:
|
|
49
|
+
return YGEdge.YGEdgeBottom
|
|
50
|
+
if flexDirection == YGFlexDirection.YGFlexDirectionColumnReverse:
|
|
51
|
+
return YGEdge.YGEdgeTop
|
|
52
|
+
if flexDirection == YGFlexDirection.YGFlexDirectionRow:
|
|
53
|
+
return YGEdge.YGEdgeRight
|
|
54
|
+
if flexDirection == YGFlexDirection.YGFlexDirectionRowReverse:
|
|
55
|
+
return YGEdge.YGEdgeLeft
|
|
56
|
+
fatalWithMessage("Invalid FlexDirection")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def inlineStartEdge(flexDirection: YGFlexDirection, direction: YGDirection) -> YGEdge:
|
|
60
|
+
if isRow(flexDirection):
|
|
61
|
+
return YGEdge.YGEdgeRight if direction == YGDirection.YGDirectionRTL else YGEdge.YGEdgeLeft
|
|
62
|
+
return YGEdge.YGEdgeTop
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def inlineEndEdge(flexDirection: YGFlexDirection, direction: YGDirection) -> YGEdge:
|
|
66
|
+
if isRow(flexDirection):
|
|
67
|
+
return YGEdge.YGEdgeLeft if direction == YGDirection.YGDirectionRTL else YGEdge.YGEdgeRight
|
|
68
|
+
return YGEdge.YGEdgeBottom
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def dimension(flexDirection: YGFlexDirection) -> YGDimension:
|
|
72
|
+
if flexDirection in (YGFlexDirection.YGFlexDirectionColumn, YGFlexDirection.YGFlexDirectionColumnReverse):
|
|
73
|
+
return YGDimension.YGDimensionHeight
|
|
74
|
+
if flexDirection in (YGFlexDirection.YGFlexDirectionRow, YGFlexDirection.YGFlexDirectionRowReverse):
|
|
75
|
+
return YGDimension.YGDimensionWidth
|
|
76
|
+
fatalWithMessage("Invalid FlexDirection")
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
|
|
4
|
+
This source code is licensed under the MIT license found in the
|
|
5
|
+
LICENSE file in the root directory of this source tree.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
|
|
12
|
+
from ..algorithm.BoundAxis import boundAxisWithinMinAndMax
|
|
13
|
+
from ..algorithm.FlexDirection import resolveDirection
|
|
14
|
+
from ..numeric.FloatMath import float32
|
|
15
|
+
from ..YGEnums import YGDirection, YGDisplay, YGPositionType, YGWrap
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class FlexLineRunningLayout:
|
|
20
|
+
totalFlexGrowFactors: float = 0.0
|
|
21
|
+
totalFlexShrinkScaledFactors: float = 0.0
|
|
22
|
+
remainingFreeSpace: float = 0.0
|
|
23
|
+
mainDim: float = 0.0
|
|
24
|
+
crossDim: float = 0.0
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class FlexLine:
|
|
29
|
+
itemsInFlow: list = field(default_factory=list)
|
|
30
|
+
sizeConsumed: float = 0.0
|
|
31
|
+
numberOfAutoMargins: int = 0
|
|
32
|
+
layout: FlexLineRunningLayout = field(default_factory=FlexLineRunningLayout)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def calculateFlexLine(
|
|
36
|
+
node,
|
|
37
|
+
ownerDirection: YGDirection,
|
|
38
|
+
ownerWidth: float,
|
|
39
|
+
mainAxisOwnerSize: float,
|
|
40
|
+
availableInnerWidth: float,
|
|
41
|
+
availableInnerMainDim: float,
|
|
42
|
+
children,
|
|
43
|
+
startIndex: int,
|
|
44
|
+
lineCount: int,
|
|
45
|
+
) -> FlexLine:
|
|
46
|
+
itemsInFlow = []
|
|
47
|
+
sizeConsumed = float32(0.0)
|
|
48
|
+
totalFlexGrowFactors = 0.0
|
|
49
|
+
totalFlexShrinkScaledFactors = 0.0
|
|
50
|
+
numberOfAutoMargins = 0
|
|
51
|
+
firstElementInLine = None
|
|
52
|
+
sizeConsumedIncludingMinConstraint = float32(0.0)
|
|
53
|
+
direction = node.resolveDirection(ownerDirection)
|
|
54
|
+
mainAxis = resolveDirection(node.style().flexDirection(), direction)
|
|
55
|
+
isNodeFlexWrap = node.style().flexWrap() != YGWrap.YGWrapNoWrap
|
|
56
|
+
gap = node.style().computeGapForAxis(mainAxis, availableInnerMainDim)
|
|
57
|
+
|
|
58
|
+
for child in children[startIndex:]:
|
|
59
|
+
if child.style().display() == YGDisplay.YGDisplayNone or child.style().positionType() == YGPositionType.YGPositionTypeAbsolute:
|
|
60
|
+
continue
|
|
61
|
+
if firstElementInLine is None:
|
|
62
|
+
firstElementInLine = child
|
|
63
|
+
if child.style().flexStartMarginIsAuto(mainAxis, ownerDirection):
|
|
64
|
+
numberOfAutoMargins += 1
|
|
65
|
+
if child.style().flexEndMarginIsAuto(mainAxis, ownerDirection):
|
|
66
|
+
numberOfAutoMargins += 1
|
|
67
|
+
child.setLineIndex(lineCount)
|
|
68
|
+
childMarginMainAxis = child.style().computeMarginForAxis(mainAxis, availableInnerWidth)
|
|
69
|
+
childLeadingGapMainAxis = 0.0 if child == firstElementInLine else gap
|
|
70
|
+
flexBasisWithMinAndMaxConstraints = boundAxisWithinMinAndMax(
|
|
71
|
+
child,
|
|
72
|
+
direction,
|
|
73
|
+
mainAxis,
|
|
74
|
+
child.getLayout().computedFlexBasis,
|
|
75
|
+
mainAxisOwnerSize,
|
|
76
|
+
ownerWidth,
|
|
77
|
+
).unwrap()
|
|
78
|
+
if (
|
|
79
|
+
sizeConsumedIncludingMinConstraint
|
|
80
|
+
+ flexBasisWithMinAndMaxConstraints
|
|
81
|
+
+ childMarginMainAxis
|
|
82
|
+
+ childLeadingGapMainAxis
|
|
83
|
+
> availableInnerMainDim
|
|
84
|
+
and isNodeFlexWrap
|
|
85
|
+
and itemsInFlow
|
|
86
|
+
):
|
|
87
|
+
break
|
|
88
|
+
sizeConsumedIncludingMinConstraint = float32(
|
|
89
|
+
sizeConsumedIncludingMinConstraint
|
|
90
|
+
+ float32(
|
|
91
|
+
flexBasisWithMinAndMaxConstraints
|
|
92
|
+
+ childMarginMainAxis
|
|
93
|
+
+ childLeadingGapMainAxis
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
sizeConsumed = float32(
|
|
97
|
+
sizeConsumed
|
|
98
|
+
+ float32(
|
|
99
|
+
flexBasisWithMinAndMaxConstraints
|
|
100
|
+
+ childMarginMainAxis
|
|
101
|
+
+ childLeadingGapMainAxis
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
if child.isNodeFlexible():
|
|
105
|
+
totalFlexGrowFactors = float32(
|
|
106
|
+
totalFlexGrowFactors + child.resolveFlexGrow()
|
|
107
|
+
)
|
|
108
|
+
totalFlexShrinkScaledFactors = float32(
|
|
109
|
+
totalFlexShrinkScaledFactors
|
|
110
|
+
+ float32(
|
|
111
|
+
-child.resolveFlexShrink()
|
|
112
|
+
* child.getLayout().computedFlexBasis.unwrap()
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
itemsInFlow.append(child)
|
|
116
|
+
|
|
117
|
+
if 0 < totalFlexGrowFactors < 1:
|
|
118
|
+
totalFlexGrowFactors = 1
|
|
119
|
+
if 0 < totalFlexShrinkScaledFactors < 1:
|
|
120
|
+
totalFlexShrinkScaledFactors = 1
|
|
121
|
+
|
|
122
|
+
return FlexLine(
|
|
123
|
+
itemsInFlow=itemsInFlow,
|
|
124
|
+
sizeConsumed=sizeConsumed,
|
|
125
|
+
numberOfAutoMargins=numberOfAutoMargins,
|
|
126
|
+
layout=FlexLineRunningLayout(
|
|
127
|
+
totalFlexGrowFactors=totalFlexGrowFactors,
|
|
128
|
+
totalFlexShrinkScaledFactors=totalFlexShrinkScaledFactors,
|
|
129
|
+
),
|
|
130
|
+
)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
|
|
4
|
+
This source code is licensed under the MIT license found in the
|
|
5
|
+
LICENSE file in the root directory of this source tree.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import math
|
|
11
|
+
|
|
12
|
+
from ..numeric.Comparison import inexactEquals, isUndefined
|
|
13
|
+
from ..YGEnums import YGDimension, YGEdge, YGNodeType
|
|
14
|
+
from ..YGPixelGrid import YGRoundValueToPixelGrid as roundValueToPixelGrid
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def roundLayoutResultsToPixelGrid(node, absoluteLeft: float, absoluteTop: float) -> None:
|
|
18
|
+
pointScaleFactor = float(node.getConfig().getPointScaleFactor())
|
|
19
|
+
nodeLeft = node.getLayout().position(YGEdge.YGEdgeLeft)
|
|
20
|
+
nodeTop = node.getLayout().position(YGEdge.YGEdgeTop)
|
|
21
|
+
nodeWidth = node.getLayout().dimension(YGDimension.YGDimensionWidth)
|
|
22
|
+
nodeHeight = node.getLayout().dimension(YGDimension.YGDimensionHeight)
|
|
23
|
+
absoluteNodeLeft = absoluteLeft + nodeLeft
|
|
24
|
+
absoluteNodeTop = absoluteTop + nodeTop
|
|
25
|
+
absoluteNodeRight = absoluteNodeLeft + nodeWidth
|
|
26
|
+
absoluteNodeBottom = absoluteNodeTop + nodeHeight
|
|
27
|
+
if pointScaleFactor != 0.0:
|
|
28
|
+
textRounding = node.getNodeType() == YGNodeType.YGNodeTypeText
|
|
29
|
+
node.setLayoutPosition(roundValueToPixelGrid(nodeLeft, pointScaleFactor, False, textRounding), YGEdge.YGEdgeLeft)
|
|
30
|
+
node.setLayoutPosition(roundValueToPixelGrid(nodeTop, pointScaleFactor, False, textRounding), YGEdge.YGEdgeTop)
|
|
31
|
+
if not isUndefined(nodeWidth):
|
|
32
|
+
scaledNodeWidth = nodeWidth * pointScaleFactor
|
|
33
|
+
hasFractionalWidth = (
|
|
34
|
+
not inexactEquals(round(scaledNodeWidth), scaledNodeWidth)
|
|
35
|
+
if math.isfinite(scaledNodeWidth)
|
|
36
|
+
else False
|
|
37
|
+
)
|
|
38
|
+
node.getLayout().setDimension(
|
|
39
|
+
YGDimension.YGDimensionWidth,
|
|
40
|
+
roundValueToPixelGrid(absoluteNodeRight, pointScaleFactor, textRounding and hasFractionalWidth, textRounding and not hasFractionalWidth)
|
|
41
|
+
- roundValueToPixelGrid(absoluteNodeLeft, pointScaleFactor, False, textRounding),
|
|
42
|
+
)
|
|
43
|
+
if not isUndefined(nodeHeight):
|
|
44
|
+
scaledNodeHeight = nodeHeight * pointScaleFactor
|
|
45
|
+
hasFractionalHeight = (
|
|
46
|
+
not inexactEquals(round(scaledNodeHeight), scaledNodeHeight)
|
|
47
|
+
if math.isfinite(scaledNodeHeight)
|
|
48
|
+
else False
|
|
49
|
+
)
|
|
50
|
+
node.getLayout().setDimension(
|
|
51
|
+
YGDimension.YGDimensionHeight,
|
|
52
|
+
roundValueToPixelGrid(absoluteNodeBottom, pointScaleFactor, textRounding and hasFractionalHeight, textRounding and not hasFractionalHeight)
|
|
53
|
+
- roundValueToPixelGrid(absoluteNodeTop, pointScaleFactor, False, textRounding),
|
|
54
|
+
)
|
|
55
|
+
for child in node.getChildren():
|
|
56
|
+
roundLayoutResultsToPixelGrid(child, absoluteNodeLeft, absoluteNodeTop)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
|
|
4
|
+
This source code is licensed under the MIT license found in the
|
|
5
|
+
LICENSE file in the root directory of this source tree.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from enum import Enum
|
|
11
|
+
|
|
12
|
+
from ..debug.AssertFatal import fatalWithMessage
|
|
13
|
+
from ..YGEnums import YGMeasureMode
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SizingMode(Enum):
|
|
17
|
+
StretchFit = 0
|
|
18
|
+
MaxContent = 1
|
|
19
|
+
FitContent = 2
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def measureMode(mode: SizingMode) -> YGMeasureMode:
|
|
23
|
+
if mode == SizingMode.StretchFit:
|
|
24
|
+
return YGMeasureMode.YGMeasureModeExactly
|
|
25
|
+
if mode == SizingMode.MaxContent:
|
|
26
|
+
return YGMeasureMode.YGMeasureModeUndefined
|
|
27
|
+
if mode == SizingMode.FitContent:
|
|
28
|
+
return YGMeasureMode.YGMeasureModeAtMost
|
|
29
|
+
fatalWithMessage("Invalid SizingMode")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def sizingMode(mode: YGMeasureMode) -> SizingMode:
|
|
33
|
+
if mode == YGMeasureMode.YGMeasureModeExactly:
|
|
34
|
+
return SizingMode.StretchFit
|
|
35
|
+
if mode == YGMeasureMode.YGMeasureModeUndefined:
|
|
36
|
+
return SizingMode.MaxContent
|
|
37
|
+
if mode == YGMeasureMode.YGMeasureModeAtMost:
|
|
38
|
+
return SizingMode.FitContent
|
|
39
|
+
fatalWithMessage("Invalid MeasureMode")
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
|
|
4
|
+
This source code is licensed under the MIT license found in the
|
|
5
|
+
LICENSE file in the root directory of this source tree.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from ..algorithm.FlexDirection import dimension, flexEndEdge, flexStartEdge
|
|
11
|
+
from ..numeric.FloatMath import float32
|
|
12
|
+
from ..YGEnums import YGFlexDirection
|
|
13
|
+
from ..node.Node import Node
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def getPositionOfOppositeEdge(position: float, axis: YGFlexDirection, containingNode: Node, node: Node) -> float:
|
|
17
|
+
return float32(
|
|
18
|
+
float32(
|
|
19
|
+
float32(containingNode.getLayout().measuredDimension(dimension(axis)))
|
|
20
|
+
- float32(node.getLayout().measuredDimension(dimension(axis)))
|
|
21
|
+
)
|
|
22
|
+
- float32(position)
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def setChildTrailingPosition(node: Node, child: Node, axis: YGFlexDirection) -> None:
|
|
27
|
+
child.setLayoutPosition(
|
|
28
|
+
getPositionOfOppositeEdge(child.getLayout().position(flexStartEdge(axis)), axis, node, child),
|
|
29
|
+
flexEndEdge(axis),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def needsTrailingPosition(axis: YGFlexDirection) -> bool:
|
|
34
|
+
return axis in (YGFlexDirection.YGFlexDirectionRowReverse, YGFlexDirection.YGFlexDirectionColumnReverse)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
|
|
4
|
+
This source code is licensed under the MIT license found in the
|
|
5
|
+
LICENSE file in the root directory of this source tree.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .AbsoluteLayout import *
|
|
9
|
+
from .Align import *
|
|
10
|
+
from .Baseline import *
|
|
11
|
+
from .BoundAxis import *
|
|
12
|
+
from .Cache import *
|
|
13
|
+
from .CalculateLayout import *
|
|
14
|
+
from .FlexLine import *
|
|
15
|
+
from .FlexDirection import *
|
|
16
|
+
from .PixelGrid import *
|
|
17
|
+
from .SizingMode import *
|
|
18
|
+
from .TrailingPosition import *
|
yoga/config/Config.py
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
|
|
4
|
+
This source code is licensed under the MIT license found in the
|
|
5
|
+
LICENSE file in the root directory of this source tree.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from typing import Any, Callable
|
|
12
|
+
|
|
13
|
+
from ..YGEnums import YGErrata, YGExperimentalFeature, YGLogLevel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
YGLogger = Callable[..., int]
|
|
17
|
+
YGCloneNodeFunc = Callable[..., Any]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _default_logger(*_args: object, **_kwargs: object) -> int:
|
|
21
|
+
return 0
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class Config:
|
|
26
|
+
cloneNodeCallback_: YGCloneNodeFunc | None = None
|
|
27
|
+
logger_: YGLogger = _default_logger
|
|
28
|
+
useWebDefaults_: bool = False
|
|
29
|
+
version_: int = 0
|
|
30
|
+
experimentalFeatures_: dict[YGExperimentalFeature, bool] = field(
|
|
31
|
+
default_factory=dict
|
|
32
|
+
)
|
|
33
|
+
errata_: YGErrata = YGErrata.YGErrataNone
|
|
34
|
+
pointScaleFactor_: float = 1.0
|
|
35
|
+
context_: Any = None
|
|
36
|
+
|
|
37
|
+
def setUseWebDefaults(self, useWebDefaults: bool) -> None:
|
|
38
|
+
self.useWebDefaults_ = useWebDefaults
|
|
39
|
+
|
|
40
|
+
def useWebDefaults(self) -> bool:
|
|
41
|
+
return self.useWebDefaults_
|
|
42
|
+
|
|
43
|
+
def setExperimentalFeatureEnabled(
|
|
44
|
+
self, feature: YGExperimentalFeature, enabled: bool
|
|
45
|
+
) -> None:
|
|
46
|
+
if self.isExperimentalFeatureEnabled(feature) != enabled:
|
|
47
|
+
self.experimentalFeatures_[feature] = enabled
|
|
48
|
+
self.version_ += 1
|
|
49
|
+
|
|
50
|
+
def isExperimentalFeatureEnabled(self, feature: YGExperimentalFeature) -> bool:
|
|
51
|
+
return self.experimentalFeatures_.get(feature, False)
|
|
52
|
+
|
|
53
|
+
def getEnabledExperiments(self) -> dict[YGExperimentalFeature, bool]:
|
|
54
|
+
return dict(self.experimentalFeatures_)
|
|
55
|
+
|
|
56
|
+
def setErrata(self, errata: YGErrata) -> None:
|
|
57
|
+
if self.errata_ != errata:
|
|
58
|
+
self.errata_ = errata
|
|
59
|
+
self.version_ += 1
|
|
60
|
+
|
|
61
|
+
def addErrata(self, errata: YGErrata) -> None:
|
|
62
|
+
if not self.hasErrata(errata):
|
|
63
|
+
self.errata_ |= errata
|
|
64
|
+
self.version_ += 1
|
|
65
|
+
|
|
66
|
+
def removeErrata(self, errata: YGErrata) -> None:
|
|
67
|
+
if self.hasErrata(errata):
|
|
68
|
+
self.errata_ &= ~errata
|
|
69
|
+
self.version_ += 1
|
|
70
|
+
|
|
71
|
+
def getErrata(self) -> YGErrata:
|
|
72
|
+
return self.errata_
|
|
73
|
+
|
|
74
|
+
def hasErrata(self, errata: YGErrata) -> bool:
|
|
75
|
+
return bool(self.errata_ & errata)
|
|
76
|
+
|
|
77
|
+
def setPointScaleFactor(self, pointScaleFactor: float) -> None:
|
|
78
|
+
if self.pointScaleFactor_ != pointScaleFactor:
|
|
79
|
+
self.pointScaleFactor_ = pointScaleFactor
|
|
80
|
+
self.version_ += 1
|
|
81
|
+
|
|
82
|
+
def getPointScaleFactor(self) -> float:
|
|
83
|
+
return self.pointScaleFactor_
|
|
84
|
+
|
|
85
|
+
def setContext(self, context: Any) -> None:
|
|
86
|
+
self.context_ = context
|
|
87
|
+
|
|
88
|
+
def getContext(self) -> Any:
|
|
89
|
+
return self.context_
|
|
90
|
+
|
|
91
|
+
def getVersion(self) -> int:
|
|
92
|
+
return self.version_
|
|
93
|
+
|
|
94
|
+
def setLogger(self, logger: YGLogger) -> None:
|
|
95
|
+
self.logger_ = logger
|
|
96
|
+
|
|
97
|
+
def log(
|
|
98
|
+
self,
|
|
99
|
+
node: object,
|
|
100
|
+
logLevel: YGLogLevel,
|
|
101
|
+
format_string: str,
|
|
102
|
+
args: tuple[object, ...] = (),
|
|
103
|
+
) -> int:
|
|
104
|
+
return self.logger_(self, node, logLevel, format_string, args)
|
|
105
|
+
|
|
106
|
+
def setCloneNodeCallback(self, cloneNode: YGCloneNodeFunc | None) -> None:
|
|
107
|
+
self.cloneNodeCallback_ = cloneNode
|
|
108
|
+
|
|
109
|
+
def cloneNode(self, node: object, owner: object, childIndex: int) -> object:
|
|
110
|
+
clone = None
|
|
111
|
+
if self.cloneNodeCallback_ is not None:
|
|
112
|
+
clone = self.cloneNodeCallback_(node, owner, childIndex)
|
|
113
|
+
if clone is None:
|
|
114
|
+
from ..YGNode import YGNodeClone
|
|
115
|
+
|
|
116
|
+
clone = YGNodeClone(node)
|
|
117
|
+
return clone
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
_DEFAULT_CONFIG = Config()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def configUpdateInvalidatesLayout(oldConfig: Config, newConfig: Config) -> bool:
|
|
124
|
+
return (
|
|
125
|
+
oldConfig.getErrata() != newConfig.getErrata()
|
|
126
|
+
or oldConfig.getPointScaleFactor() != newConfig.getPointScaleFactor()
|
|
127
|
+
or oldConfig.useWebDefaults() != newConfig.useWebDefaults()
|
|
128
|
+
or oldConfig.getEnabledExperiments() != newConfig.getEnabledExperiments()
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def resolveRef(ref: Config | None) -> Config | None:
|
|
133
|
+
return ref
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def getDefaultConfig() -> Config:
|
|
137
|
+
return _DEFAULT_CONFIG
|
yoga/config/__init__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
|
|
4
|
+
This source code is licensed under the MIT license found in the
|
|
5
|
+
LICENSE file in the root directory of this source tree.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def assertFatal(condition: bool, message: str) -> None:
|
|
10
|
+
if not condition:
|
|
11
|
+
raise AssertionError(message)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def assertFatalWithConfig(_config, condition: bool, message: str) -> None:
|
|
15
|
+
assertFatal(condition, message)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def assertFatalWithNode(_node, condition: bool, message: str) -> None:
|
|
19
|
+
assertFatal(condition, message)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def fatalWithMessage(message: str) -> None:
|
|
23
|
+
raise RuntimeError(message)
|
|
24
|
+
|
yoga/debug/Log.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
|
|
4
|
+
This source code is licensed under the MIT license found in the
|
|
5
|
+
LICENSE file in the root directory of this source tree.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from ..YGEnums import YGLogLevel
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def getDefaultLogger():
|
|
16
|
+
"""Get the default logger that does nothing."""
|
|
17
|
+
def _logger(*_args: object, **_kwargs: object) -> int:
|
|
18
|
+
return 0
|
|
19
|
+
return _logger
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def log(node: Any | None, level: YGLogLevel, format_string: str, *args: object) -> int:
|
|
23
|
+
"""
|
|
24
|
+
Log a message at the given level.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
node: The yoga node (can be None)
|
|
28
|
+
level: The log level
|
|
29
|
+
format_string: The format string
|
|
30
|
+
*args: Arguments to format into the string
|
|
31
|
+
"""
|
|
32
|
+
if node is None:
|
|
33
|
+
# Log without node
|
|
34
|
+
logger = getDefaultLogger()
|
|
35
|
+
return logger(None, None, level, format_string, args)
|
|
36
|
+
|
|
37
|
+
config = node.getConfig() if node is not None else None
|
|
38
|
+
logger = config.logger_ if config is not None else getDefaultLogger()
|
|
39
|
+
return logger(config, node, level, format_string, args)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def logWithConfig(config: Any | None, level: YGLogLevel, format_string: str, *args: object) -> int:
|
|
43
|
+
"""Log a message with a config but no node."""
|
|
44
|
+
if config is None:
|
|
45
|
+
logger = getDefaultLogger()
|
|
46
|
+
return logger(None, None, level, format_string, args)
|
|
47
|
+
logger = config.logger_ if hasattr(config, 'logger_') else getDefaultLogger()
|
|
48
|
+
return logger(config, None, level, format_string, args)
|
|
49
|
+
|
yoga/debug/__init__.py
ADDED