mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 11:01:21 +08:00

* chore: move tns-core-modules to nativescript-core * chore: preparing compat generate script * chore: add missing definitions * chore: no need for http-request to be private * chore: packages chore * test: generate tests for tns-core-modules * chore: add anroid module for consistency * chore: add .npmignore * chore: added privateModulesWhitelist * chore(webpack): added bundle-entry-points * chore: scripts * chore: tests changed to use @ns/core * test: add scoped-packages test project * test: fix types * test: update test project * chore: build scripts * chore: update build script * chore: npm scripts cleanup * chore: make the compat pgk work with old wp config * test: generate diff friendly tests * chore: create barrel exports * chore: move files after rebase * chore: typedoc config * chore: compat mode * chore: review of barrels * chore: remove tns-core-modules import after rebase * chore: dev workflow setup * chore: update developer-workflow * docs: experiment with API extractor * chore: api-extractor and barrel exports * chore: api-extractor configs * chore: generate d.ts rollup with api-extractor * refactor: move methods inside Frame * chore: fic tests to use Frame static methods * refactor: create Builder class * refactor: use Builder class in tests * refactor: include Style in ui barrel * chore: separate compat build script * chore: fix tslint errors * chore: update NATIVESCRIPT_CORE_ARGS * chore: fix compat pack * chore: fix ui-test-app build with linked modules * chore: Application, ApplicationSettings, Connectivity and Http * chore: export Trace, Profiling and Utils * refactor: Static create methods for ImageSource * chore: fix deprecated usages of ImageSource * chore: move Span and FormattedString to ui * chore: add events-args and ImageSource to index files * chore: check for CLI >= 6.2 when building for IOS * chore: update travis build * chore: copy Pod file to compat package * chore: update error msg ui-tests-app * refactor: Apply suggestions from code review Co-Authored-By: Martin Yankov <m.i.yankov@gmail.com> * chore: typings and refs * chore: add missing d.ts files for public API * chore: adress code review FB * chore: update api-report * chore: dev-workflow for other apps * chore: api update * chore: update api-report
201 lines
8.8 KiB
TypeScript
201 lines
8.8 KiB
TypeScript
import { WrapLayoutBase, View, layout } from "./wrap-layout-common";
|
|
|
|
export * from "./wrap-layout-common";
|
|
|
|
export class WrapLayout extends WrapLayoutBase {
|
|
private _lengths: Array<number> = new Array<number>();
|
|
|
|
private static getChildMeasureSpec(parentMode: number, parentLength: number, itemLength): number {
|
|
if (itemLength > 0) {
|
|
return layout.makeMeasureSpec(itemLength, layout.EXACTLY);
|
|
}
|
|
else if (parentMode === layout.UNSPECIFIED) {
|
|
return layout.makeMeasureSpec(0, layout.UNSPECIFIED);
|
|
}
|
|
else {
|
|
return layout.makeMeasureSpec(parentLength, layout.AT_MOST);
|
|
}
|
|
}
|
|
|
|
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
|
|
let measureWidth = 0;
|
|
let measureHeight = 0;
|
|
|
|
const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
|
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
|
|
|
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
|
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
|
|
|
const horizontalPaddingsAndMargins = this.effectivePaddingLeft + this.effectivePaddingRight + this.effectiveBorderLeftWidth + this.effectiveBorderRightWidth;
|
|
const verticalPaddingsAndMargins = this.effectivePaddingTop + this.effectivePaddingBottom + this.effectiveBorderTopWidth + this.effectiveBorderBottomWidth;
|
|
|
|
const availableWidth = widthMode === layout.UNSPECIFIED ? Number.MAX_VALUE : width - horizontalPaddingsAndMargins;
|
|
const availableHeight = heightMode === layout.UNSPECIFIED ? Number.MAX_VALUE : height - verticalPaddingsAndMargins;
|
|
|
|
const childWidthMeasureSpec: number = WrapLayout.getChildMeasureSpec(widthMode, availableWidth, this.effectiveItemWidth);
|
|
const childHeightMeasureSpec: number = WrapLayout.getChildMeasureSpec(heightMode, availableHeight, this.effectiveItemHeight);
|
|
|
|
let remainingWidth = availableWidth;
|
|
let remainingHeight = availableHeight;
|
|
|
|
this._lengths.length = 0;
|
|
let rowOrColumn = 0;
|
|
let maxLength = 0;
|
|
|
|
const isVertical = this.orientation === "vertical";
|
|
|
|
let useItemWidth: boolean = this.effectiveItemWidth > 0;
|
|
let useItemHeight: boolean = this.effectiveItemHeight > 0;
|
|
let itemWidth = this.effectiveItemWidth;
|
|
let itemHeight = this.effectiveItemHeight;
|
|
|
|
this.eachLayoutChild((child, last) => {
|
|
const desiredSize = View.measureChild(this, child, childWidthMeasureSpec, childHeightMeasureSpec);
|
|
let childMeasuredWidth = useItemWidth ? itemWidth : desiredSize.measuredWidth;
|
|
let childMeasuredHeight = useItemHeight ? itemHeight : desiredSize.measuredHeight;
|
|
let isFirst = this._lengths.length <= rowOrColumn;
|
|
|
|
if (isVertical) {
|
|
if (childMeasuredHeight > remainingHeight) {
|
|
rowOrColumn++;
|
|
maxLength = Math.max(maxLength, measureHeight);
|
|
measureHeight = childMeasuredHeight;
|
|
remainingHeight = availableHeight - childMeasuredHeight;
|
|
this._lengths[isFirst ? rowOrColumn - 1 : rowOrColumn] = childMeasuredWidth;
|
|
}
|
|
else {
|
|
remainingHeight -= childMeasuredHeight;
|
|
measureHeight += childMeasuredHeight;
|
|
}
|
|
}
|
|
else {
|
|
if (childMeasuredWidth > remainingWidth) {
|
|
rowOrColumn++;
|
|
maxLength = Math.max(maxLength, measureWidth);
|
|
measureWidth = childMeasuredWidth;
|
|
remainingWidth = availableWidth - childMeasuredWidth;
|
|
this._lengths[isFirst ? rowOrColumn - 1 : rowOrColumn] = childMeasuredHeight;
|
|
}
|
|
else {
|
|
remainingWidth -= childMeasuredWidth;
|
|
measureWidth += childMeasuredWidth;
|
|
}
|
|
}
|
|
|
|
if (isFirst) {
|
|
this._lengths[rowOrColumn] = isVertical ? childMeasuredWidth : childMeasuredHeight;
|
|
}
|
|
else {
|
|
this._lengths[rowOrColumn] = Math.max(this._lengths[rowOrColumn], isVertical ? childMeasuredWidth : childMeasuredHeight);
|
|
}
|
|
});
|
|
|
|
if (isVertical) {
|
|
measureHeight = Math.max(maxLength, measureHeight);
|
|
this._lengths.forEach((value, index, array) => {
|
|
measureWidth += value;
|
|
});
|
|
}
|
|
else {
|
|
measureWidth = Math.max(maxLength, measureWidth);
|
|
this._lengths.forEach((value, index, array) => {
|
|
measureHeight += value;
|
|
});
|
|
}
|
|
|
|
measureWidth += horizontalPaddingsAndMargins;
|
|
measureHeight += verticalPaddingsAndMargins;
|
|
|
|
// Check against our minimum sizes
|
|
measureWidth = Math.max(measureWidth, this.effectiveMinWidth);
|
|
measureHeight = Math.max(measureHeight, this.effectiveMinHeight);
|
|
|
|
const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
|
const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
|
|
|
this.setMeasuredDimension(widthAndState, heightAndState);
|
|
}
|
|
|
|
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
|
super.onLayout(left, top, right, bottom);
|
|
|
|
const insets = this.getSafeAreaInsets();
|
|
const isVertical = this.orientation === "vertical";
|
|
const paddingLeft = this.effectiveBorderLeftWidth + this.effectivePaddingLeft + insets.left;
|
|
const paddingTop = this.effectiveBorderTopWidth + this.effectivePaddingTop + insets.top;
|
|
const paddingRight = this.effectiveBorderRightWidth + this.effectivePaddingRight + insets.right;
|
|
const paddingBottom = this.effectiveBorderBottomWidth + this.effectivePaddingBottom + insets.bottom;
|
|
|
|
let childLeft = paddingLeft;
|
|
let childTop = paddingTop;
|
|
let childrenHeight = bottom - top - paddingBottom;
|
|
let childrenWidth = right - left - paddingRight;
|
|
let rowOrColumn = 0;
|
|
|
|
this.eachLayoutChild((child, last) => {
|
|
// Add margins because layoutChild will sustract them.
|
|
// * density converts them to device pixels.
|
|
let childHeight = child.getMeasuredHeight() + child.effectiveMarginTop + child.effectiveMarginBottom;
|
|
let childWidth = child.getMeasuredWidth() + child.effectiveMarginLeft + child.effectiveMarginRight;
|
|
|
|
let length = this._lengths[rowOrColumn];
|
|
if (isVertical) {
|
|
childWidth = length;
|
|
childHeight = this.effectiveItemHeight > 0 ? this.effectiveItemHeight : childHeight;
|
|
let isFirst = childTop === paddingTop;
|
|
if (childTop + childHeight > childrenHeight && childLeft + childWidth <= childrenWidth) {
|
|
// Move to top.
|
|
childTop = paddingTop;
|
|
|
|
if (!isFirst) {
|
|
// Move to right with current column width.
|
|
childLeft += length;
|
|
}
|
|
|
|
// Move to next column.
|
|
rowOrColumn++;
|
|
|
|
// Take respective column width.
|
|
childWidth = this._lengths[isFirst ? rowOrColumn - 1 : rowOrColumn];
|
|
}
|
|
|
|
if (childLeft < childrenWidth && childTop < childrenHeight) {
|
|
View.layoutChild(this, child, childLeft, childTop, childLeft + childWidth, childTop + childHeight);
|
|
}
|
|
|
|
// Move next child Top position to bottom.
|
|
childTop += childHeight;
|
|
} else {
|
|
childWidth = this.effectiveItemWidth > 0 ? this.effectiveItemWidth : childWidth;
|
|
childHeight = length;
|
|
let isFirst = childLeft === paddingLeft;
|
|
if (childLeft + childWidth > childrenWidth && childTop + childHeight <= childrenHeight) {
|
|
// Move to left.
|
|
childLeft = paddingLeft;
|
|
|
|
if (!isFirst) {
|
|
// Move to bottom with current row height.
|
|
childTop += length;
|
|
}
|
|
|
|
// Move to next row.
|
|
rowOrColumn++;
|
|
|
|
// Take respective row height.
|
|
childHeight = this._lengths[isFirst ? rowOrColumn - 1 : rowOrColumn];
|
|
}
|
|
|
|
if (childLeft < childrenWidth && childTop < childrenHeight) {
|
|
View.layoutChild(this, child, childLeft, childTop, childLeft + childWidth, childTop + childHeight);
|
|
}
|
|
|
|
// Move next child Left position to right.
|
|
childLeft += childWidth;
|
|
}
|
|
});
|
|
}
|
|
}
|