1 |
|
2 | import { layout } from '../../../../utils';
|
3 | import { Trace } from '../../../../trace';
|
4 | export 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 |
|
124 | if (childLength >= 0) {
|
125 |
|
126 |
|
127 |
|
128 | resultSize = parentSpecMode === layout.UNSPECIFIED ? childLength : Math.min(parentLength, childLength);
|
129 | resultMode = layout.EXACTLY;
|
130 | }
|
131 | else {
|
132 | switch (parentSpecMode) {
|
133 |
|
134 | case layout.EXACTLY:
|
135 | resultSize = Math.max(0, parentLength - margins);
|
136 |
|
137 |
|
138 | resultMode = stretched ? layout.EXACTLY : layout.AT_MOST;
|
139 | break;
|
140 |
|
141 | case layout.AT_MOST:
|
142 | resultSize = Math.max(0, parentLength - margins);
|
143 | resultMode = layout.AT_MOST;
|
144 | break;
|
145 |
|
146 | case layout.UNSPECIFIED:
|
147 | resultSize = 0;
|
148 | resultMode = layout.UNSPECIFIED;
|
149 | break;
|
150 | }
|
151 | }
|
152 | return layout.makeMeasureSpec(resultSize, resultMode);
|
153 | }
|
154 | }
|
155 |
|
\ | No newline at end of file |