Merged PR 162: Implement symbols and other stuff (see desc)

Implement symbols
- Add, Remove, Select Container
- Form
- Link with container
- Symbol behavior application to container (move to x with xpositionreference)

Important changes
- Remove SelectedContainer from HistoryState, meaning that it will be slower for each load but will be faster for each operations* (SetHistory, SelectContainer, DeleteContainer, SymbolOperations)
- ElementsSidebar now opens with isSidebarOpen meaning that both sidebar will open on toggle
- Moved camelize, transformX, restoreX to different modules (stringtools.ts, svg.ts)
This commit is contained in:
Eric Nguyen 2022-08-22 13:58:32 +00:00
parent 58ef28fe89
commit 8b8d88f885
48 changed files with 1453 additions and 188 deletions

View file

@ -2,19 +2,20 @@ import { Dispatch, SetStateAction } from 'react';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { IConfiguration } from '../../Interfaces/IConfiguration';
import { ContainerModel, IContainerModel } from '../../Interfaces/IContainerModel';
import { findContainerById } from '../../utils/itertools';
import { getCurrentHistory } from './Editor';
import { findContainerById, MakeIterator } from '../../utils/itertools';
import { getCurrentHistory, UpdateCounters } from './Editor';
import { AddMethod } from '../../Enums/AddMethod';
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { GetDefaultContainerProps, DEFAULTCHILDTYPE_ALLOW_CYCLIC, DEFAULTCHILDTYPE_MAX_DEPTH } from '../../utils/default';
import { ApplyBehaviors } from './Behaviors/Behaviors';
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
/**
* Select a container
* @param container Selected container
*/
export function SelectContainer(
container: ContainerModel,
containerId: string,
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
@ -23,19 +24,13 @@ export function SelectContainer(
const history = getCurrentHistory(fullHistory, historyCurrentStep);
const current = history[history.length - 1];
const mainContainerClone = structuredClone(current.MainContainer);
const selectedContainer = findContainerById(mainContainerClone, container.properties.id);
if (selectedContainer === undefined) {
throw new Error('[SelectContainer] Cannot find container among children of main container!');
}
history.push({
LastAction: `Select ${selectedContainer.properties.id}`,
MainContainer: mainContainerClone,
SelectedContainer: selectedContainer,
SelectedContainerId: selectedContainer.properties.id,
TypeCounters: Object.assign({}, current.TypeCounters)
LastAction: `Select ${containerId}`,
MainContainer: structuredClone(current.MainContainer),
SelectedContainerId: containerId,
TypeCounters: Object.assign({}, current.TypeCounters),
Symbols: structuredClone(current.Symbols),
SelectedSymbolId: current.SelectedSymbolId
});
setHistory(history);
setHistoryCurrentStep(history.length - 1);
@ -76,6 +71,8 @@ export function DeleteContainer(
if (container === null || container === undefined) {
throw new Error('[DeleteContainer] Container model was not found among children of the main container!');
}
const newSymbols = structuredClone(current.Symbols)
UnlinkSymbol(newSymbols, container);
const index = container.parent.children.indexOf(container);
if (index > -1) {
@ -94,14 +91,26 @@ export function DeleteContainer(
history.push({
LastAction: `Delete ${containerId}`,
MainContainer: mainContainerClone,
SelectedContainer,
SelectedContainerId,
TypeCounters: Object.assign({}, current.TypeCounters)
TypeCounters: Object.assign({}, current.TypeCounters),
Symbols: newSymbols,
SelectedSymbolId: current.SelectedSymbolId
});
setHistory(history);
setHistoryCurrentStep(history.length - 1);
}
function UnlinkSymbol(symbols: Map<string, ISymbolModel>, container: IContainerModel): void {
const it = MakeIterator(container);
for (const child of it) {
const symbol = symbols.get(child.properties.linkedSymbolId);
if (symbol === undefined) {
continue;
}
symbol.linkedContainers.delete(child.properties.id);
}
}
/**
* Add a new container to a selected container
* @param type The type of container
@ -114,21 +123,19 @@ export function DeleteContainer(
*/
export function AddContainerToSelectedContainer(
type: string,
selected: IContainerModel | undefined,
configuration: IConfiguration,
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep);
const current = history[history.length - 1];
if (current.SelectedContainer === null ||
current.SelectedContainer === undefined) {
if (selected === null ||
selected === undefined) {
return;
}
const parent = current.SelectedContainer;
const parent = selected;
AddContainer(
parent.children.length,
type,
@ -166,11 +173,6 @@ export function AddContainer(
const history = getCurrentHistory(fullHistory, historyCurrentStep);
const current = history[history.length - 1];
if (current.MainContainer === null ||
current.MainContainer === undefined) {
return;
}
// Get the preset properties from the API
const containerConfig = configuration.AvailableContainers
.find(option => option.Type === type);
@ -220,7 +222,7 @@ export function AddContainer(
}
);
ApplyBehaviors(newContainer);
ApplyBehaviors(newContainer, current.Symbols);
// And push it the the parent children
if (index === parentClone.children.length) {
@ -235,23 +237,15 @@ export function AddContainer(
history.push({
LastAction: `Add ${newContainer.properties.id} in ${parentClone.properties.id}`,
MainContainer: clone,
SelectedContainer: parentClone,
SelectedContainerId: parentClone.properties.id,
TypeCounters: newCounters
TypeCounters: newCounters,
Symbols: structuredClone(current.Symbols),
SelectedSymbolId: current.SelectedSymbolId
});
setHistory(history);
setHistoryCurrentStep(history.length - 1);
}
function UpdateCounters(counters: Record<string, number>, type: string): void {
if (counters[type] === null ||
counters[type] === undefined) {
counters[type] = 0;
} else {
counters[type]++;
}
}
function InitializeDefaultChild(
configuration: IConfiguration,
containerConfig: IAvailableContainer,