242 lines
7.7 KiB
TypeScript
242 lines
7.7 KiB
TypeScript
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';
|
|
|
|
/**
|
|
* Select a container
|
|
* @param container Selected container
|
|
*/
|
|
export function SelectContainer(
|
|
container: ContainerModel,
|
|
fullHistory: IHistoryState[],
|
|
historyCurrentStep: number,
|
|
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
|
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
|
): void {
|
|
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!');
|
|
}
|
|
|
|
setHistory(history.concat([{
|
|
LastAction: `Select container ${selectedContainer.properties.id}`,
|
|
MainContainer: mainContainerClone,
|
|
SelectedContainer: selectedContainer,
|
|
SelectedContainerId: selectedContainer.properties.id,
|
|
TypeCounters: Object.assign({}, current.TypeCounters)
|
|
}]));
|
|
setHistoryCurrentStep(history.length);
|
|
}
|
|
|
|
/**
|
|
* Delete a container
|
|
* @param containerId containerId of the container to delete
|
|
* @param fullHistory History of the editor
|
|
* @param historyCurrentStep Current step
|
|
* @param setHistory State setter for History
|
|
* @param setHistoryCurrentStep State setter for current step
|
|
*/
|
|
export function DeleteContainer(
|
|
containerId: string,
|
|
fullHistory: IHistoryState[],
|
|
historyCurrentStep: number,
|
|
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
|
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
|
): void {
|
|
const history = getCurrentHistory(fullHistory, historyCurrentStep);
|
|
const current = history[historyCurrentStep];
|
|
|
|
const mainContainerClone: IContainerModel = structuredClone(current.MainContainer);
|
|
const container = findContainerById(mainContainerClone, containerId);
|
|
|
|
if (container === undefined) {
|
|
throw new Error(`[DeleteContainer] Tried to delete a container that is not present in the main container: ${containerId}`);
|
|
}
|
|
|
|
if (container === mainContainerClone ||
|
|
container.parent === undefined ||
|
|
container.parent === null) {
|
|
// TODO: Implement alert
|
|
throw new Error('[DeleteContainer] Tried to delete the main container! Deleting the main container is not allowed!');
|
|
}
|
|
|
|
if (container === null || container === undefined) {
|
|
throw new Error('[DeleteContainer] Container model was not found among children of the main container!');
|
|
}
|
|
|
|
const index = container.parent.children.indexOf(container);
|
|
if (index > -1) {
|
|
container.parent.children.splice(index, 1);
|
|
} else {
|
|
throw new Error('[DeleteContainer] Could not find container among parent\'s children');
|
|
}
|
|
|
|
// Select the previous container
|
|
// or select the one above
|
|
const SelectedContainer = findContainerById(mainContainerClone, current.SelectedContainerId) ??
|
|
container.parent.children.at(index - 1) ??
|
|
container.parent;
|
|
const SelectedContainerId = SelectedContainer.properties.id;
|
|
|
|
setHistory(history.concat([{
|
|
LastAction: `Delete container ${containerId}`,
|
|
MainContainer: mainContainerClone,
|
|
SelectedContainer,
|
|
SelectedContainerId,
|
|
TypeCounters: Object.assign({}, current.TypeCounters)
|
|
}]));
|
|
setHistoryCurrentStep(history.length);
|
|
}
|
|
|
|
/**
|
|
* Add a new container to a selected container
|
|
* @param type The type of container
|
|
* @param configuration Configuration of the App
|
|
* @param fullHistory History of the editor
|
|
* @param historyCurrentStep Current step
|
|
* @param setHistory State setter for History
|
|
* @param setHistoryCurrentStep State setter for current step
|
|
* @returns void
|
|
*/
|
|
export function AddContainerToSelectedContainer(
|
|
type: string,
|
|
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) {
|
|
return;
|
|
}
|
|
|
|
const parent = current.SelectedContainer;
|
|
AddContainer(
|
|
parent.children.length,
|
|
type,
|
|
parent.properties.id,
|
|
configuration,
|
|
fullHistory,
|
|
historyCurrentStep,
|
|
setHistory,
|
|
setHistoryCurrentStep
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create and add a new container at `index` in children of parent of `parentId`
|
|
* @param index Index where to insert to the new container
|
|
* @param type Type of container
|
|
* @param parentId Parent in which to insert the new container
|
|
* @param configuration Configuration of the app
|
|
* @param fullHistory History of the editor
|
|
* @param historyCurrentStep Current step
|
|
* @param setHistory State setter of History
|
|
* @param setHistoryCurrentStep State setter of the current step
|
|
* @returns void
|
|
*/
|
|
export function AddContainer(
|
|
index: number,
|
|
type: string,
|
|
parentId: string,
|
|
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.MainContainer === null ||
|
|
current.MainContainer === undefined) {
|
|
return;
|
|
}
|
|
|
|
// Get the preset properties from the API
|
|
const properties = configuration.AvailableContainers
|
|
.find(option => option.Type === type);
|
|
|
|
if (properties === undefined) {
|
|
throw new Error(`[AddContainer] Object type not found. Found: ${type}`);
|
|
}
|
|
|
|
// Set the counter of the object type in order to assign an unique id
|
|
const newCounters = Object.assign({}, current.TypeCounters);
|
|
if (newCounters[type] === null ||
|
|
newCounters[type] === undefined) {
|
|
newCounters[type] = 0;
|
|
} else {
|
|
newCounters[type]++;
|
|
}
|
|
const count = newCounters[type];
|
|
|
|
// Create maincontainer model
|
|
const clone: IContainerModel = structuredClone(current.MainContainer);
|
|
|
|
// Find the parent
|
|
const parentClone: IContainerModel | undefined = findContainerById(
|
|
clone, parentId
|
|
);
|
|
|
|
if (parentClone === null || parentClone === undefined) {
|
|
throw new Error('[AddContainer] Container model was not found among children of the main container!');
|
|
}
|
|
|
|
let x = 0;
|
|
if (index > 0) {
|
|
const lastChild: IContainerModel | undefined = parentClone.children.at(index - 1);
|
|
if (lastChild !== undefined) {
|
|
x = lastChild.properties.x + Number(lastChild.properties.width);
|
|
}
|
|
}
|
|
|
|
// Create the container
|
|
const newContainer = new ContainerModel(
|
|
parentClone,
|
|
{
|
|
id: `${type}-${count}`,
|
|
parentId: parentClone.properties.id,
|
|
x,
|
|
y: 0,
|
|
width: properties?.Width,
|
|
height: parentClone.properties.height,
|
|
isRigidBody: false,
|
|
XPositionReference: properties.XPositionReference,
|
|
...properties.Style
|
|
},
|
|
[],
|
|
{
|
|
type
|
|
}
|
|
);
|
|
|
|
// And push it the the parent children
|
|
if (index === parentClone.children.length) {
|
|
parentClone.children.push(newContainer);
|
|
} else {
|
|
parentClone.children.splice(index, 0, newContainer);
|
|
}
|
|
|
|
// Update the state
|
|
setHistory(history.concat([{
|
|
LastAction: 'Add container',
|
|
MainContainer: clone,
|
|
SelectedContainer: parentClone,
|
|
SelectedContainerId: parentClone.properties.id,
|
|
TypeCounters: newCounters
|
|
}]));
|
|
setHistoryCurrentStep(history.length);
|
|
}
|