stackPanel.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import { Tools } from "babylonjs/Misc/tools";
  2. import { Container } from "./container";
  3. import { Measure } from "../measure";
  4. import { Control } from "./control";
  5. import { _TypeStore } from 'babylonjs/Misc/typeStore';
  6. /**
  7. * Class used to create a 2D stack panel container
  8. */
  9. export class StackPanel extends Container {
  10. private _isVertical = true;
  11. private _manualWidth = false;
  12. private _manualHeight = false;
  13. private _doNotTrackManualChanges = false;
  14. /**
  15. * Gets or sets a boolean indicating that layou warnings should be ignored
  16. */
  17. public ignoreLayoutWarnings = false;
  18. /** Gets or sets a boolean indicating if the stack panel is vertical or horizontal*/
  19. public get isVertical(): boolean {
  20. return this._isVertical;
  21. }
  22. public set isVertical(value: boolean) {
  23. if (this._isVertical === value) {
  24. return;
  25. }
  26. this._isVertical = value;
  27. this._markAsDirty();
  28. }
  29. /**
  30. * Gets or sets panel width.
  31. * This value should not be set when in horizontal mode as it will be computed automatically
  32. */
  33. public set width(value: string | number) {
  34. if (!this._doNotTrackManualChanges) {
  35. this._manualWidth = true;
  36. }
  37. if (this._width.toString(this._host) === value) {
  38. return;
  39. }
  40. if (this._width.fromString(value)) {
  41. this._markAsDirty();
  42. }
  43. }
  44. public get width(): string | number {
  45. return this._width.toString(this._host);
  46. }
  47. /**
  48. * Gets or sets panel height.
  49. * This value should not be set when in vertical mode as it will be computed automatically
  50. */
  51. public set height(value: string | number) {
  52. if (!this._doNotTrackManualChanges) {
  53. this._manualHeight = true;
  54. }
  55. if (this._height.toString(this._host) === value) {
  56. return;
  57. }
  58. if (this._height.fromString(value)) {
  59. this._markAsDirty();
  60. }
  61. }
  62. public get height(): string | number {
  63. return this._height.toString(this._host);
  64. }
  65. /**
  66. * Creates a new StackPanel
  67. * @param name defines control name
  68. */
  69. constructor(public name?: string) {
  70. super(name);
  71. }
  72. protected _getTypeName(): string {
  73. return "StackPanel";
  74. }
  75. /** @hidden */
  76. protected _preMeasure(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
  77. for (var child of this._children) {
  78. if (this._isVertical) {
  79. child.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
  80. } else {
  81. child.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  82. }
  83. }
  84. super._preMeasure(parentMeasure, context);
  85. }
  86. protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
  87. super._additionalProcessing(parentMeasure, context);
  88. this._measureForChildren.copyFrom(parentMeasure);
  89. this._measureForChildren.left = this._currentMeasure.left;
  90. this._measureForChildren.top = this._currentMeasure.top;
  91. if (!this.isVertical || this._manualWidth) {
  92. this._measureForChildren.width = this._currentMeasure.width;
  93. }
  94. if (this.isVertical || this._manualHeight) {
  95. this._measureForChildren.height = this._currentMeasure.height;
  96. }
  97. }
  98. protected _postMeasure(): void {
  99. var stackWidth = 0;
  100. var stackHeight = 0;
  101. for (var child of this._children) {
  102. if (!child.isVisible || child.notRenderable) {
  103. continue;
  104. }
  105. if (this._isVertical) {
  106. if (child.top !== stackHeight + "px") {
  107. child.top = stackHeight + "px";
  108. this._rebuildLayout = true;
  109. child._top.ignoreAdaptiveScaling = true;
  110. }
  111. if (child._height.isPercentage) {
  112. if (!this.ignoreLayoutWarnings) {
  113. Tools.Warn(`Control (Name:${child.name}, UniqueId:${child.uniqueId}) is using height in percentage mode inside a vertical StackPanel`);
  114. }
  115. } else {
  116. stackHeight += child._currentMeasure.height + child.paddingTopInPixels + child.paddingBottomInPixels;
  117. }
  118. } else {
  119. if (child.left !== stackWidth + "px") {
  120. child.left = stackWidth + "px";
  121. this._rebuildLayout = true;
  122. child._left.ignoreAdaptiveScaling = true;
  123. }
  124. if (child._width.isPercentage) {
  125. if (!this.ignoreLayoutWarnings) {
  126. Tools.Warn(`Control (Name:${child.name}, UniqueId:${child.uniqueId}) is using width in percentage mode inside a horizontal StackPanel`);
  127. }
  128. } else {
  129. stackWidth += child._currentMeasure.width + child.paddingLeftInPixels + child.paddingRightInPixels;
  130. }
  131. }
  132. }
  133. this._doNotTrackManualChanges = true;
  134. // Let stack panel width or height default to stackHeight and stackWidth if dimensions are not specified.
  135. // User can now define their own height and width for stack panel.
  136. let panelWidthChanged = false;
  137. let panelHeightChanged = false;
  138. if (!this._manualHeight && this._isVertical) { // do not specify height if strictly defined by user
  139. let previousHeight = this.height;
  140. this.height = stackHeight + "px";
  141. panelHeightChanged = previousHeight !== this.height || !this._height.ignoreAdaptiveScaling;
  142. }
  143. if (!this._manualWidth && !this._isVertical) { // do not specify width if strictly defined by user
  144. let previousWidth = this.width;
  145. this.width = stackWidth + "px";
  146. panelWidthChanged = previousWidth !== this.width || !this._width.ignoreAdaptiveScaling;
  147. }
  148. if (panelHeightChanged) {
  149. this._height.ignoreAdaptiveScaling = true;
  150. }
  151. if (panelWidthChanged) {
  152. this._width.ignoreAdaptiveScaling = true;
  153. }
  154. this._doNotTrackManualChanges = false;
  155. if (panelWidthChanged || panelHeightChanged) {
  156. this._rebuildLayout = true;
  157. }
  158. super._postMeasure();
  159. }
  160. }
  161. _TypeStore.RegisteredTypes["BABYLON.GUI.StackPanel"] = StackPanel;