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 = 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; }