stackPanel.ts 5.8 KB

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