@babylonjs/gui
Version:
For usage documentation please visit the [GUI documentation](https://doc.babylonjs.com/features/featuresDeepDive/gui/).
246 lines • 9.23 kB
JavaScript
import { __decorate } from "@babylonjs/core/tslib.es6.js";
import { Container } from "./container.js";
import { Control } from "./control.js";
import { RegisterClass } from "@babylonjs/core/Misc/typeStore.js";
import { serialize } from "@babylonjs/core/Misc/decorators.js";
import { Logger } from "@babylonjs/core/Misc/logger.js";
/**
* Class used to create a 2D stack panel container
*/
export class StackPanel extends Container {
/** Gets or sets a boolean indicating if the stack panel is vertical or horizontal*/
get isVertical() {
return this._isVertical;
}
set isVertical(value) {
if (this._isVertical === value) {
return;
}
this._isVertical = value;
this._markAsDirty();
}
/**
* Gets or sets the spacing (in pixels) between each child.
*/
get spacing() {
return this._spacing;
}
set spacing(value) {
if (this._spacing === value) {
return;
}
this._spacing = value;
this._markAsDirty();
}
/**
* Gets or sets panel width.
* This value should not be set when in horizontal mode as it will be computed automatically
*/
set width(value) {
if (!this._doNotTrackManualChanges) {
this._manualWidth = true;
}
if (this._width.toString(this._host) === value) {
return;
}
if (this._width.fromString(value)) {
this._markAsDirty();
}
}
get width() {
return this._width.toString(this._host);
}
/**
* Gets or sets panel height.
* This value should not be set when in vertical mode as it will be computed automatically
*/
set height(value) {
if (!this._doNotTrackManualChanges) {
this._manualHeight = true;
}
if (this._height.toString(this._host) === value) {
return;
}
if (this._height.fromString(value)) {
this._markAsDirty();
}
}
get height() {
return this._height.toString(this._host);
}
/**
* Creates a new StackPanel
* @param name defines control name
*/
constructor(name) {
super(name);
this.name = name;
this._isVertical = true;
this._manualWidth = false;
this._manualHeight = false;
this._doNotTrackManualChanges = false;
this._spacing = 0;
/**
* Gets or sets a boolean indicating that layout warnings should be ignored
*/
this.ignoreLayoutWarnings = false;
}
_getTypeName() {
return "StackPanel";
}
/**
* @internal
*/
_preMeasure(parentMeasure, context) {
for (const child of this._children) {
if (this._isVertical) {
child.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
}
else {
child.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
}
}
super._preMeasure(parentMeasure, context);
}
_additionalProcessing(parentMeasure, context) {
super._additionalProcessing(parentMeasure, context);
this._measureForChildren.copyFrom(parentMeasure);
this._measureForChildren.left = this._currentMeasure.left;
this._measureForChildren.top = this._currentMeasure.top;
if (!this.isVertical || this._manualWidth) {
this._measureForChildren.width = this._currentMeasure.width;
}
if (this.isVertical || this._manualHeight) {
this._measureForChildren.height = this._currentMeasure.height;
}
}
_postMeasure() {
let stackWidth = 0;
let stackHeight = 0;
const childrenCount = this._children.length;
// Calculate scaled spacing using idealRatio (same pattern as shadowOffset)
const scaledSpacing = this._spacing * this._host.idealRatio;
for (let index = 0; index < childrenCount; index++) {
const child = this._children[index];
if (!child.isVisible || child.notRenderable) {
continue;
}
if (this._isVertical) {
const top = stackHeight + "px";
if (child.top !== top) {
child.top = top;
this._rebuildLayout = true;
child._top.ignoreAdaptiveScaling = true;
}
if (!this.ignoreLayoutWarnings && !child.isDimensionFullyDefined("height")) {
Logger.Warn(`Control (Name:${child.name}, UniqueId:${child.uniqueId}) is using height in percentage mode inside a vertical StackPanel`, 1);
}
else {
stackHeight += child._currentMeasure.height + child._paddingTopInPixels + child._paddingBottomInPixels + (index < childrenCount - 1 ? scaledSpacing : 0);
}
}
else {
const left = stackWidth + "px";
if (child.left !== left) {
child.left = left;
this._rebuildLayout = true;
child._left.ignoreAdaptiveScaling = true;
}
if (!this.ignoreLayoutWarnings && !child.isDimensionFullyDefined("width")) {
Logger.Warn(`Control (Name:${child.name}, UniqueId:${child.uniqueId}) is using width in percentage mode inside a horizontal StackPanel`, 1);
}
else {
stackWidth += child._currentMeasure.width + child._paddingLeftInPixels + child._paddingRightInPixels + (index < childrenCount - 1 ? scaledSpacing : 0);
}
}
}
stackWidth += this._paddingLeftInPixels + this._paddingRightInPixels;
stackHeight += this._paddingTopInPixels + this._paddingBottomInPixels;
this._doNotTrackManualChanges = true;
// Let stack panel width or height default to stackHeight and stackWidth if dimensions are not specified.
// User can now define their own height and width for stack panel.
let panelWidthChanged = false;
let panelHeightChanged = false;
if ((!this._manualHeight || this.adaptHeightToChildren) && this._isVertical) {
// do not specify height if strictly defined by user
const previousHeight = this.height;
this.height = stackHeight + "px";
panelHeightChanged = previousHeight !== this.height || !this._height.ignoreAdaptiveScaling;
}
if ((!this._manualWidth || this.adaptWidthToChildren) && !this._isVertical) {
// do not specify width if strictly defined by user
const previousWidth = this.width;
this.width = stackWidth + "px";
panelWidthChanged = previousWidth !== this.width || !this._width.ignoreAdaptiveScaling;
}
if (panelHeightChanged) {
this._height.ignoreAdaptiveScaling = true;
}
if (panelWidthChanged) {
this._width.ignoreAdaptiveScaling = true;
}
this._doNotTrackManualChanges = false;
if (panelWidthChanged || panelHeightChanged) {
this._rebuildLayout = true;
}
super._postMeasure();
}
_getManualDim(dim) {
if (dim === "width") {
return this._manualWidth;
}
else {
return this._manualHeight;
}
}
isDimensionFullyDefined(dim) {
if (dim === "height" ? this.isVertical : !this.isVertical && !this._getManualDim(dim)) {
for (const child of this._children) {
if (!child.isDimensionFullyDefined(dim)) {
return false;
}
}
return true;
}
return this.getDimension(dim).isPixel || this._getAdaptDimTo(dim);
}
/**
* Serializes the current control
* @param serializationObject defined the JSON serialized object
* @param force force serialization even if isSerializable === false
* @param allowCanvas defines if the control is allowed to use a Canvas2D object to serialize
*/
serialize(serializationObject, force, allowCanvas) {
super.serialize(serializationObject, force, allowCanvas);
if (!this.isSerializable && !force) {
return;
}
serializationObject.manualWidth = this._manualWidth;
serializationObject.manualHeight = this._manualHeight;
}
/**
* @internal
*/
_parseFromContent(serializedObject, host) {
this._manualWidth = serializedObject.manualWidth;
this._manualHeight = serializedObject.manualHeight;
super._parseFromContent(serializedObject, host);
}
}
__decorate([
serialize()
], StackPanel.prototype, "ignoreLayoutWarnings", void 0);
__decorate([
serialize()
], StackPanel.prototype, "isVertical", null);
__decorate([
serialize()
], StackPanel.prototype, "spacing", null);
__decorate([
serialize()
], StackPanel.prototype, "width", null);
__decorate([
serialize()
], StackPanel.prototype, "height", null);
RegisterClass("BABYLON.GUI.StackPanel", StackPanel);
//# sourceMappingURL=stackPanel.js.map