Merged PR 167: Add Flex and fix bugs (read desc)

Note: The branch name does not fit the new features.

- Implement Flex with simplex
- Enable rigid body by default (removed IsRigidBody property) <=== possibly a bad idea
- Sort children in add and update properties
- Implement MaxWidth
- Add more docs

Fixes :
- .env.production url
- Symbols: not blocking the linked container when the parent is moving
This commit is contained in:
Eric Nguyen 2022-08-25 13:28:32 +00:00
parent ec3fddec9d
commit 7f3f6a489a
43 changed files with 1127 additions and 453 deletions

View file

@ -10,6 +10,9 @@ import { GetDefaultContainerProps, DEFAULTCHILDTYPE_ALLOW_CYCLIC, DEFAULTCHILDTY
import { ApplyBehaviors } from '../Behaviors/Behaviors';
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
import Swal from 'sweetalert2';
import { ApplyMargin, transformX } from '../../../utils/svg';
import { Flex } from '../Behaviors/FlexBehaviors';
import { PropertyType } from '../../../Enums/PropertyType';
/**
* Select a container
@ -87,6 +90,8 @@ export function DeleteContainer(
throw new Error('[DeleteContainer] Could not find container among parent\'s children');
}
Flex(container);
// Select the previous container
// or select the one above
const SelectedContainerId = GetSelectedContainerOnDelete(
@ -147,7 +152,7 @@ export function AddContainerToSelectedContainer(
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
if (selected === null ||
selected === undefined) {
selected === undefined) {
return;
}
@ -213,9 +218,17 @@ export function AddContainer(
if (parentClone === null || parentClone === undefined) {
throw new Error('[AddContainer] Container model was not found among children of the main container!');
}
const left: number = containerConfig.Margin?.left ?? 0;
const bottom: number = containerConfig.Margin?.bottom ?? 0;
const top: number = containerConfig.Margin?.top ?? 0;
const right: number = containerConfig.Margin?.right ?? 0;
let x = containerConfig.DefaultX ?? 0;
const y = containerConfig.DefaultY ?? 0;
let y = containerConfig.DefaultY ?? 0;
let width = containerConfig.Width ?? containerConfig.MaxWidth ?? containerConfig.MinWidth ?? parentClone.properties.width;
let height = containerConfig.Height ?? parentClone.properties.height;
({ x, y, width, height } = ApplyMargin(x, y, width, height, left, bottom, top, right));
x = ApplyAddMethod(index, containerConfig, parentClone, x);
@ -225,6 +238,8 @@ export function AddContainer(
parentClone,
x,
y,
width,
height,
containerConfig
);
@ -238,17 +253,15 @@ export function AddContainer(
}
);
ApplyBehaviors(newContainer, current.Symbols);
// And push it the the parent children
if (index === parentClone.children.length) {
parentClone.children.push(newContainer);
} else {
parentClone.children.splice(index, 0, newContainer);
}
parentClone.children.push(newContainer);
UpdateParentChildrenList(parentClone);
InitializeDefaultChild(configuration, containerConfig, newContainer, newCounters);
ApplyBehaviors(newContainer, current.Symbols);
ApplyBehaviorsOnSiblings(newContainer, current.Symbols);
// Update the state
history.push({
LastAction: `Add ${newContainer.properties.id} in ${parentClone.properties.id}`,
@ -262,6 +275,16 @@ export function AddContainer(
setHistoryCurrentStep(history.length - 1);
}
function UpdateParentChildrenList(parentClone: IContainerModel | null): void {
if (parentClone === null) {
return;
}
parentClone.children.sort(
(a, b) => transformX(a.properties.x, a.properties.width, a.properties.XPositionReference) -
transformX(b.properties.x, b.properties.width, b.properties.XPositionReference)
);
}
function InitializeDefaultChild(
configuration: IConfiguration,
containerConfig: IAvailableContainer,
@ -286,8 +309,17 @@ function InitializeDefaultChild(
}
seen.add(currentConfig.Type);
const x = currentConfig.DefaultX ?? 0;
const y = currentConfig.DefaultY ?? 0;
const left: number = currentConfig.Margin?.left ?? 0;
const bottom: number = currentConfig.Margin?.bottom ?? 0;
const top: number = currentConfig.Margin?.top ?? 0;
const right: number = currentConfig.Margin?.right ?? 0;
let x = currentConfig.DefaultX ?? 0;
let y = currentConfig.DefaultY ?? 0;
let width = currentConfig.Width ?? currentConfig.MaxWidth ?? currentConfig.MinWidth ?? parent.properties.width;
let height = currentConfig.Height ?? parent.properties.height;
({ x, y, width, height } = ApplyMargin(x, y, width, height, left, bottom, top, right));
UpdateCounters(newCounters, currentConfig.Type);
const count = newCounters[currentConfig.Type];
@ -297,6 +329,8 @@ function InitializeDefaultChild(
parent,
x,
y,
width,
height,
currentConfig
);
@ -353,7 +387,7 @@ function ApplyAddMethod(index: number, containerConfig: IAvailableContainer, par
export function OnPropertyChange(
key: string,
value: string | number | boolean,
isStyle: boolean = false,
type: PropertyType = PropertyType.SIMPLE,
selected: IContainerModel | undefined,
fullHistory: IHistoryState[],
historyCurrentStep: number,
@ -364,7 +398,7 @@ export function OnPropertyChange(
const current = history[history.length - 1];
if (selected === null ||
selected === undefined) {
selected === undefined) {
throw new Error('[OnPropertyChange] Property was changed before selecting a Container');
}
@ -375,22 +409,7 @@ export function OnPropertyChange(
throw new Error('[OnPropertyChange] Container model was not found among children of the main container!');
}
const oldSymbolId = container.properties.linkedSymbolId;
if (isStyle) {
(container.properties.style as any)[key] = value;
} else {
(container.properties as any)[key] = value;
}
LinkSymbol(
container.properties.id,
oldSymbolId,
container.properties.linkedSymbolId,
current.Symbols
);
ApplyBehaviors(container, current.Symbols);
SetContainer(container, key, value, type, current.Symbols);
history.push({
LastAction: `Change ${key} of ${container.properties.id}`,
@ -404,6 +423,79 @@ export function OnPropertyChange(
setHistoryCurrentStep(history.length - 1);
}
/**
* Set the container with properties and behaviors (mutate)
* @param container Container to update
* @param key Key of the property to update
* @param value Value of the property to update
* @param type Type of the property to update
* @param symbols Current list of symbols
*/
function SetContainer(
container: ContainerModel,
key: string, value: string | number | boolean,
type: PropertyType,
symbols: Map<string, ISymbolModel>
): void {
// get the old symbol to detect unlink
const oldSymbolId = container.properties.linkedSymbolId;
// update the property
AssignProperty(container, key, value, type);
// link the symbol if it exists
LinkSymbol(
container.properties.id,
oldSymbolId,
container.properties.linkedSymbolId,
symbols
);
// Apply special behaviors: rigid, flex, symbol, anchor
ApplyBehaviors(container, symbols);
// Apply special behaviors on siblings
ApplyBehaviorsOnSiblings(container, symbols);
// sort the children list by their position
UpdateParentChildrenList(container.parent);
}
function AssignProperty(container: ContainerModel, key: string, value: string | number | boolean, type: PropertyType): void {
switch (type) {
case PropertyType.STYLE:
(container.properties.style as any)[key] = value;
break;
case PropertyType.MARGIN:
SetMargin();
break;
default:
(container.properties as any)[key] = value;
}
function SetMargin(): void {
const oldMarginValue: number = (container.properties.margin as any)[key];
const diff = Number(value) - oldMarginValue;
switch (key) {
case 'left':
container.properties.x += diff;
container.properties.width -= diff;
break;
case 'right':
container.properties.width -= diff;
break;
case 'bottom':
container.properties.height -= diff;
break;
case 'top':
container.properties.y += diff;
container.properties.height -= diff;
break;
}
(container.properties.margin as any)[key] = value;
}
}
function LinkSymbol(
containerId: string,
oldSymbolId: string,
@ -422,3 +514,10 @@ function LinkSymbol(
newSymbol.linkedContainers.add(containerId);
}
function ApplyBehaviorsOnSiblings(newContainer: ContainerModel, Symbols: Map<string, ISymbolModel>): void {
if (newContainer.parent === null || newContainer.parent === undefined) {
return;
}
newContainer.parent.children.filter(container => newContainer !== container).forEach(container => ApplyBehaviors(container, Symbols));
}