- Implements API methods through right click - Refactor events - Refactor usage of setHistory and setHistoryCurrentStep into a single function - Update ContainerOperations documentations - Added AddContainers in order to add multiple containers + refactor AddContainer to use it - Fix regression - Fix AddContainer at index
164 lines
5.2 KiB
TypeScript
164 lines
5.2 KiB
TypeScript
import { Dispatch, SetStateAction } from 'react';
|
|
import { IConfiguration } from '../../../Interfaces/IConfiguration';
|
|
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
|
import { IHistoryState } from '../../../Interfaces/IHistoryState';
|
|
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
|
import { GetDefaultSymbolModel } from '../../../utils/default';
|
|
import { FindContainerById } from '../../../utils/itertools';
|
|
import { RestoreX } from '../../../utils/svg';
|
|
import { ApplyBehaviors } from '../Behaviors/Behaviors';
|
|
import { GetCurrentHistory, UpdateCounters } from '../Editor';
|
|
|
|
export function AddSymbol(
|
|
name: string,
|
|
configuration: IConfiguration,
|
|
fullHistory: IHistoryState[],
|
|
historyCurrentStep: number
|
|
): IHistoryState[] {
|
|
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
|
const current = history[history.length - 1];
|
|
|
|
const symbolConfig = configuration.AvailableSymbols
|
|
.find(option => option.Name === name);
|
|
|
|
if (symbolConfig === undefined) {
|
|
throw new Error('[AddSymbol] Symbol could not be found in the config');
|
|
}
|
|
const type = `symbol-${name}`;
|
|
const newCounters = structuredClone(current.typeCounters);
|
|
UpdateCounters(newCounters, type);
|
|
|
|
const newSymbols = structuredClone(current.symbols);
|
|
const newSymbol: ISymbolModel = GetDefaultSymbolModel(name, newCounters, type, symbolConfig);
|
|
newSymbol.x = RestoreX(newSymbol.x, newSymbol.width, newSymbol.config.XPositionReference);
|
|
|
|
newSymbols.set(newSymbol.id, newSymbol);
|
|
|
|
history.push({
|
|
lastAction: `Add ${name}`,
|
|
mainContainer: structuredClone(current.mainContainer),
|
|
selectedContainerId: current.selectedContainerId,
|
|
typeCounters: newCounters,
|
|
symbols: newSymbols,
|
|
selectedSymbolId: newSymbol.id
|
|
});
|
|
return history;
|
|
}
|
|
|
|
export function SelectSymbol(
|
|
symbolId: string,
|
|
fullHistory: IHistoryState[],
|
|
historyCurrentStep: number
|
|
): IHistoryState[] {
|
|
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
|
const current = history[history.length - 1];
|
|
|
|
history.push({
|
|
lastAction: `Select ${symbolId}`,
|
|
mainContainer: structuredClone(current.mainContainer),
|
|
selectedContainerId: current.selectedContainerId,
|
|
typeCounters: structuredClone(current.typeCounters),
|
|
symbols: structuredClone(current.symbols),
|
|
selectedSymbolId: symbolId
|
|
});
|
|
return history;
|
|
}
|
|
|
|
export function DeleteSymbol(
|
|
symbolId: string,
|
|
fullHistory: IHistoryState[],
|
|
historyCurrentStep: number
|
|
): IHistoryState[] {
|
|
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
|
const current = history[history.length - 1];
|
|
|
|
const newSymbols = structuredClone(current.symbols);
|
|
const symbol = newSymbols.get(symbolId);
|
|
|
|
if (symbol === undefined) {
|
|
throw new Error(`[DeleteSymbol] Could not find symbol in the current state!: ${symbolId}`);
|
|
}
|
|
|
|
const newMainContainer = structuredClone(current.mainContainer);
|
|
|
|
UnlinkSymbolFromContainers(symbol, newMainContainer);
|
|
|
|
newSymbols.delete(symbolId);
|
|
|
|
history.push({
|
|
lastAction: `Select ${symbolId}`,
|
|
mainContainer: newMainContainer,
|
|
selectedContainerId: current.selectedContainerId,
|
|
typeCounters: structuredClone(current.typeCounters),
|
|
symbols: newSymbols,
|
|
selectedSymbolId: symbolId
|
|
});
|
|
return history;
|
|
}
|
|
|
|
/**
|
|
* Unlink a symbol to a container and its children
|
|
* @param symbol Symbol to remove
|
|
* @param root Container and its children to remove a symbol from
|
|
*/
|
|
function UnlinkSymbolFromContainers(symbol: ISymbolModel, root: IContainerModel): void {
|
|
symbol.linkedContainers.forEach((containerId) => {
|
|
const container = FindContainerById(root, containerId);
|
|
|
|
if (container === undefined) {
|
|
return;
|
|
}
|
|
|
|
container.properties.linkedSymbolId = '';
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Handled the property change event in the properties form
|
|
* @param key Property name
|
|
* @param value New value of the property
|
|
* @returns void
|
|
*/
|
|
export function OnPropertyChange(
|
|
key: string,
|
|
value: string | number | boolean,
|
|
fullHistory: IHistoryState[],
|
|
historyCurrentStep: number
|
|
): IHistoryState[] {
|
|
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
|
const current = history[history.length - 1];
|
|
|
|
if (current.selectedSymbolId === '') {
|
|
throw new Error('[OnSymbolPropertyChange] Property was changed before selecting a symbol');
|
|
}
|
|
|
|
const newSymbols: Map<string, ISymbolModel> = structuredClone(current.symbols);
|
|
const symbol = newSymbols.get(current.selectedSymbolId);
|
|
|
|
if (symbol === null || symbol === undefined) {
|
|
throw new Error('[OnSymbolPropertyChange] Symbol model was not found in state!');
|
|
}
|
|
|
|
(symbol as any)[key] = value;
|
|
|
|
const newMainContainer = structuredClone(current.mainContainer);
|
|
symbol.linkedContainers.forEach((containerId) => {
|
|
const container = FindContainerById(newMainContainer, containerId);
|
|
|
|
if (container === undefined) {
|
|
return;
|
|
}
|
|
|
|
ApplyBehaviors(container, newSymbols);
|
|
});
|
|
|
|
history.push({
|
|
lastAction: `Change ${key} of ${symbol.id}`,
|
|
mainContainer: newMainContainer,
|
|
selectedContainerId: current.selectedContainerId,
|
|
typeCounters: Object.assign({}, current.typeCounters),
|
|
symbols: newSymbols,
|
|
selectedSymbolId: symbol.id
|
|
});
|
|
return history;
|
|
}
|