remove JS layouting

This commit is contained in:
Aran-Fey
2024-06-09 10:16:36 +02:00
committed by Jakob Pinterits
parent 6e4975cce0
commit fe5c5abfa6
74 changed files with 373 additions and 2957 deletions
+34 -210
View File
@@ -1,5 +1,4 @@
import { componentsById } from '../componentManagement';
import { LayoutContext } from '../layouting';
import { ComponentId } from '../dataModels';
import { ComponentBase, ComponentState } from './componentBase';
@@ -10,7 +9,7 @@ export type LinearContainerState = ComponentState & {
proportions?: 'homogeneous' | number[] | null;
};
class LinearContainer extends ComponentBase {
abstract class LinearContainer extends ComponentBase {
state: Required<LinearContainerState>;
protected nGrowers: number; // Number of children that grow in the major axis
@@ -27,19 +26,36 @@ class LinearContainer extends ComponentBase {
deltaState: LinearContainerState,
latentComponents: Set<ComponentBase>
): void {
super.updateElement(deltaState, latentComponents);
// Children
if (deltaState.children !== undefined) {
this.replaceChildren(
latentComponents,
deltaState.children,
this.element
this.element,
true
);
// Clear everybody's position
for (let childElement of this.element
.children as Iterable<HTMLElement>) {
childElement.style.left = '0';
childElement.style.top = '0';
// Set the children's `flex-grow`
let hasGrowers = false;
for (let [index, childId] of deltaState.children.entries()) {
let childComponent = componentsById[childId]!;
let childWrapper = this.element.children[index] as HTMLElement;
if (this.getGrow(childComponent)) {
hasGrowers = true;
childWrapper.style.flexGrow = '1';
} else {
childWrapper.style.flexGrow = '0';
}
}
// If nobody wants to grow, all of them do
if (!hasGrowers) {
for (let childWrapper of this.element.children) {
(childWrapper as HTMLElement).style.flexGrow = '1';
}
}
}
@@ -54,118 +70,24 @@ class LinearContainer extends ComponentBase {
deltaState.proportions === null
) {
} else if (deltaState.proportions === 'homogeneous') {
throw new Error('not implemented yet');
this.totalProportions = this.children.size;
} else {
throw new Error('not implemented yet');
this.totalProportions = deltaState.proportions.reduce(
(a, b) => a + b
);
}
// Re-layout
this.makeLayoutDirty();
}
/// Returns whether the given component grows in the direction of the
/// container
abstract getGrow(childComponent: ComponentBase): boolean;
}
export class RowComponent extends LinearContainer {
updateNaturalWidth(ctx: LayoutContext): void {
if (this.state.proportions === null) {
this.naturalWidth = 0;
this.nGrowers = 0;
// Add up all children's requested widths
for (let child of this.children) {
this.naturalWidth += child.requestedWidth;
this.nGrowers += child.state._grow_[0] as any as number;
}
} else {
// When proportions are set, growers are ignored. Extra space is
// distributed among all children.
// Each child has a requested width and a proportion number, which
// essentially "cuts" the child into a certain number of equally
// sized pieces. In order to find our natural width, we need to
// determine the width of the largest piece, then multiply that by
// the number of total pieces.
let proportions =
this.state.proportions === 'homogeneous'
? Array(this.children.size).fill(1)
: this.state.proportions;
let maxProportionSize = 0;
for (let i = 0; i < proportions.length; i++) {
let child = componentsById[this.state.children[i]]!;
let proportion = proportions[i];
if (proportion !== 0) {
let proportionSize = child.requestedWidth / proportion;
maxProportionSize = Math.max(
maxProportionSize,
proportionSize
);
}
}
this.naturalWidth = maxProportionSize * this.totalProportions;
}
// Account for spacing
this.naturalWidth +=
Math.max(this.children.size - 1, 0) * this.state.spacing;
}
updateAllocatedWidth(ctx: LayoutContext): void {
if (this.state.proportions === null) {
// If no child wants to grow, we pretend that all of them do.
let forceGrow = this.nGrowers === 0;
let nGrowers = forceGrow
? this.state.children.length
: this.nGrowers;
let additionalSpace = this.allocatedWidth - this.naturalWidth;
let additionalSpacePerGrower = additionalSpace / nGrowers;
for (let child of this.children) {
child.allocatedWidth = child.requestedWidth;
if (child.state._grow_[0] || forceGrow) {
child.allocatedWidth += additionalSpacePerGrower;
}
}
} else {
let proportions =
this.state.proportions === 'homogeneous'
? Array(this.children.size).fill(1)
: this.state.proportions;
let spacing =
Math.max(this.children.size - 1, 0) * this.state.spacing;
let proportionSize =
(this.allocatedWidth - spacing) / this.totalProportions;
for (let i = 0; i < proportions.length; i++) {
let child = componentsById[this.state.children[i]]!;
child.allocatedWidth = proportionSize * proportions[i];
}
}
}
updateNaturalHeight(ctx: LayoutContext): void {
this.naturalHeight = 0;
for (let child of this.children) {
this.naturalHeight = Math.max(
this.naturalHeight,
child.requestedHeight
);
}
}
updateAllocatedHeight(ctx: LayoutContext): void {
// Assign the allocated height to the children
for (let child of this.children) {
child.allocatedHeight = this.allocatedHeight;
}
getGrow(childComponent: ComponentBase): boolean {
return childComponent.state._grow_[0];
}
}
@@ -176,105 +98,7 @@ export class ColumnComponent extends LinearContainer {
return element;
}
updateNaturalWidth(ctx: LayoutContext): void {
this.naturalWidth = 0;
for (let child of this.children) {
this.naturalWidth = Math.max(
this.naturalWidth,
child.requestedWidth
);
}
}
updateAllocatedWidth(ctx: LayoutContext): void {
// Assign the allocated width to the children
for (let child of this.children) {
child.allocatedWidth = this.allocatedWidth;
}
}
updateNaturalHeight(ctx: LayoutContext): void {
if (this.state.proportions === null) {
this.naturalHeight = 0;
this.nGrowers = 0;
// Add up all children's requested heights
for (let child of this.children) {
this.naturalHeight += child.requestedHeight;
this.nGrowers += child.state._grow_[1] as any as number;
}
} else {
// When proportions are set, growers are ignored. Extra space is
// distributed among all children.
// Each child has a requested width and a proportion number, which
// essentially "cuts" the child into a certain number of equally
// sized pieces. In order to find our natural width, we need to
// determine the width of the largest piece, then multiply that by
// the number of total pieces.
let proportions =
this.state.proportions === 'homogeneous'
? Array(this.children.size).fill(1)
: this.state.proportions;
let maxProportionSize = 0;
for (let i = 0; i < proportions.length; i++) {
let child = componentsById[this.state.children[i]]!;
let proportion = proportions[i];
if (proportion !== 0) {
let proportionSize = child.requestedHeight / proportion;
maxProportionSize = Math.max(
maxProportionSize,
proportionSize
);
}
}
this.naturalHeight = maxProportionSize * this.totalProportions;
}
// Account for spacing
this.naturalHeight +=
Math.max(this.children.size - 1, 0) * this.state.spacing;
}
updateAllocatedHeight(ctx: LayoutContext): void {
// Assign the allocated height to the children
if (this.state.proportions === null) {
// If no child wants to grow, we pretend that all of them do.
let forceGrow = this.nGrowers === 0;
let nGrowers = forceGrow
? this.state.children.length
: this.nGrowers;
let additionalSpace = this.allocatedHeight - this.naturalHeight;
let additionalSpacePerGrower = additionalSpace / nGrowers;
for (let child of this.children) {
child.allocatedHeight = child.requestedHeight;
if (child.state._grow_[1] || forceGrow) {
child.allocatedHeight += additionalSpacePerGrower;
}
}
} else {
let proportions =
this.state.proportions === 'homogeneous'
? Array(this.children.size).fill(1)
: this.state.proportions;
let spacing =
Math.max(this.children.size - 1, 0) * this.state.spacing;
let proportionSize =
(this.allocatedHeight - spacing) / this.totalProportions;
for (let i = 0; i < proportions.length; i++) {
let child = componentsById[this.state.children[i]]!;
child.allocatedHeight = proportionSize * proportions[i];
}
}
getGrow(childComponent: ComponentBase): boolean {
return childComponent.state._grow_[1];
}
}