7.47 kBJavaScriptView Raw
1// Requires
2import { layout } from '../../../../utils';
3import { Trace } from '../../../../trace';
4export class ViewHelper {
5 static measureChild(parent, child, widthMeasureSpec, heightMeasureSpec) {
6 let measureWidth = 0;
7 let measureHeight = 0;
8 if (child && !child.isCollapsed) {
9 const widthSpec = parent ? parent._currentWidthMeasureSpec : widthMeasureSpec;
10 const heightSpec = parent ? parent._currentHeightMeasureSpec : heightMeasureSpec;
11 const width = layout.getMeasureSpecSize(widthSpec);
12 const widthMode = layout.getMeasureSpecMode(widthSpec);
13 const height = layout.getMeasureSpecSize(heightSpec);
14 const heightMode = layout.getMeasureSpecMode(heightSpec);
15 child._updateEffectiveLayoutValues(width, widthMode, height, heightMode);
16 const style = child.style;
17 const horizontalMargins = child.effectiveMarginLeft + child.effectiveMarginRight;
18 const verticalMargins = child.effectiveMarginTop + child.effectiveMarginBottom;
19 const childWidthMeasureSpec = ViewHelper.getMeasureSpec(widthMeasureSpec, horizontalMargins, child.effectiveWidth, style.horizontalAlignment === 'stretch');
20 const childHeightMeasureSpec = ViewHelper.getMeasureSpec(heightMeasureSpec, verticalMargins, child.effectiveHeight, style.verticalAlignment === 'stretch');
21 if (Trace.isEnabled()) {
22 Trace.write(`${child.parent} :measureChild: ${child} ${layout.measureSpecToString(childWidthMeasureSpec)}, ${layout.measureSpecToString(childHeightMeasureSpec)}}`, Trace.categories.Layout);
23 }
24 child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
25 measureWidth = Math.round(child.getMeasuredWidth() + horizontalMargins);
26 measureHeight = Math.round(child.getMeasuredHeight() + verticalMargins);
27 }
28 return { measuredWidth: measureWidth, measuredHeight: measureHeight };
29 }
30 static layoutChild(parent, child, left, top, right, bottom, setFrame = true) {
31 if (!child || child.isCollapsed) {
32 return;
33 }
34 const childStyle = child.style;
35 let childTop;
36 let childLeft;
37 let childWidth = child.getMeasuredWidth();
38 let childHeight = child.getMeasuredHeight();
39 const effectiveMarginTop = child.effectiveMarginTop;
40 const effectiveMarginBottom = child.effectiveMarginBottom;
41 let vAlignment;
42 if (child.effectiveHeight >= 0 && childStyle.verticalAlignment === 'stretch') {
43 vAlignment = 'middle';
44 }
45 else {
46 vAlignment = childStyle.verticalAlignment;
47 }
48 switch (vAlignment) {
49 case 'top':
50 childTop = top + effectiveMarginTop;
51 break;
52 case 'middle':
53 childTop = top + (bottom - top - childHeight + (effectiveMarginTop - effectiveMarginBottom)) / 2;
54 break;
55 case 'bottom':
56 childTop = bottom - childHeight - effectiveMarginBottom;
57 break;
58 case 'stretch':
59 default:
60 childTop = top + effectiveMarginTop;
61 childHeight = bottom - top - (effectiveMarginTop + effectiveMarginBottom);
62 break;
63 }
64 const effectiveMarginLeft = child.effectiveMarginLeft;
65 const effectiveMarginRight = child.effectiveMarginRight;
66 let hAlignment;
67 if (child.effectiveWidth >= 0 && childStyle.horizontalAlignment === 'stretch') {
68 hAlignment = 'center';
69 }
70 else {
71 hAlignment = childStyle.horizontalAlignment;
72 }
73 switch (hAlignment) {
74 case 'left':
75 childLeft = left + effectiveMarginLeft;
76 break;
77 case 'center':
78 childLeft = left + (right - left - childWidth + (effectiveMarginLeft - effectiveMarginRight)) / 2;
79 break;
80 case 'right':
81 childLeft = right - childWidth - effectiveMarginRight;
82 break;
83 case 'stretch':
84 default:
85 childLeft = left + effectiveMarginLeft;
86 childWidth = right - left - (effectiveMarginLeft + effectiveMarginRight);
87 break;
88 }
89 const childRight = Math.round(childLeft + childWidth);
90 const childBottom = Math.round(childTop + childHeight);
91 childLeft = Math.round(childLeft);
92 childTop = Math.round(childTop);
93 if (Trace.isEnabled()) {
94 Trace.write(child.parent + ' :layoutChild: ' + child + ' ' + childLeft + ', ' + childTop + ', ' + childRight + ', ' + childBottom, Trace.categories.Layout);
95 }
96 child.layout(childLeft, childTop, childRight, childBottom, setFrame);
97 }
98 static resolveSizeAndState(size, specSize, specMode, childMeasuredState) {
99 let result = size;
100 switch (specMode) {
101 case layout.UNSPECIFIED:
102 result = Math.ceil(size);
103 break;
104 case layout.AT_MOST:
105 if (specSize < size) {
106 result = Math.ceil(specSize) | layout.MEASURED_STATE_TOO_SMALL;
107 }
108 break;
109 case layout.EXACTLY:
110 result = Math.ceil(specSize);
111 break;
112 }
113 return result | (childMeasuredState & layout.MEASURED_STATE_MASK);
114 }
115 static combineMeasuredStates(curState, newState) {
116 return curState | newState;
117 }
118 static getMeasureSpec(parentSpec, margins, childLength, stretched) {
119 const parentLength = layout.getMeasureSpecSize(parentSpec);
120 const parentSpecMode = layout.getMeasureSpecMode(parentSpec);
121 let resultSize;
122 let resultMode;
123 // We want a specific size... let be it.
124 if (childLength >= 0) {
125 // If mode !== UNSPECIFIED we take the smaller of parentLength and childLength
126 // Otherwise we will need to clip the view but this is not possible in all Android API levels.
127 // TODO: remove Math.min(parentLength, childLength)
128 resultSize = parentSpecMode === layout.UNSPECIFIED ? childLength : Math.min(parentLength, childLength);
129 resultMode = layout.EXACTLY;
130 }
131 else {
132 switch (parentSpecMode) {
133 // Parent has imposed an exact size on us
134 case layout.EXACTLY:
135 resultSize = Math.max(0, parentLength - margins);
136 // if stretched - nativeView wants to be our size. So be it.
137 // else - nativeView wants to determine its own size. It can't be bigger than us.
138 resultMode = stretched ? layout.EXACTLY : layout.AT_MOST;
139 break;
140 // Parent has imposed a maximum size on us
141 case layout.AT_MOST:
142 resultSize = Math.max(0, parentLength - margins);
143 resultMode = layout.AT_MOST;
144 break;
145 // Equivalent to measure with Infinity.
146 case layout.UNSPECIFIED:
147 resultSize = 0;
148 resultMode = layout.UNSPECIFIED;
149 break;
150 }
151 }
152 return layout.makeMeasureSpec(resultSize, resultMode);
153 }
154}
155//# sourceMappingURL=view-helper-common.js.map
\No newline at end of file