401 lines
11 KiB
TypeScript
401 lines
11 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { AddContainer as AddContainerAction, AddContainerToSelectedContainer as AddContainerToSelectedContainerAction } from '../Components/Editor/Actions/AddContainer';
|
|
import { DeleteContainer as DeleteContainerAction, SelectContainer as SelectContainerAction } from '../Components/Editor/Actions/ContainerOperations';
|
|
import { AddSymbol as AddSymbolAction, DeleteSymbol as DeleteSymbolAction, SelectSymbol as SelectSymbolAction } from '../Components/Editor/Actions/SymbolOperations';
|
|
import { GetCurrentHistory } from '../Components/Editor/Editor';
|
|
import { IConfiguration } from '../Interfaces/IConfiguration';
|
|
import { IEditorState } from '../Interfaces/IEditorState';
|
|
import { IHistoryState } from '../Interfaces/IHistoryState';
|
|
import { FindContainerById } from '../utils/itertools';
|
|
import { GetCircularReplacer } from '../utils/saveload';
|
|
|
|
interface IEditorEventParams {
|
|
root: Element | Document
|
|
editorState: IEditorState
|
|
setNewHistory: (newHistory: IHistoryState[], historyCurrentStep?: number) => void
|
|
eventInitDict?: CustomEventInit
|
|
}
|
|
export interface IEditorEvent {
|
|
name: string
|
|
func: (params: IEditorEventParams) => void
|
|
}
|
|
|
|
export const events: IEditorEvent[] = [
|
|
{ name: 'getEditorState', func: GetEditorState },
|
|
{ name: 'getEditorStateAsString', func: GetEditorStateAsString },
|
|
{ name: 'setHistory', func: SetHistory },
|
|
{ name: 'getCurrentHistoryState', func: GetCurrentHistoryState },
|
|
{ name: 'appendNewState', func: AppendNewState },
|
|
{ name: 'addContainer', func: AddContainer },
|
|
{ name: 'addContainerToSelectedContainer', func: AddContainerToSelectedContainer },
|
|
{ name: 'appendContainer', func: AppendContainer },
|
|
{ name: 'appendContainerToSelectedContainer', func: AppendContainerToSelectedContainer },
|
|
{ name: 'selectContainer', func: SelectContainer },
|
|
{ name: 'deleteContainer', func: DeleteContainer },
|
|
{ name: 'addSymbol', func: AddSymbol },
|
|
{ name: 'selectSymbol', func: SelectSymbol },
|
|
{ name: 'deleteSymbol', func: DeleteSymbol }
|
|
];
|
|
|
|
export function UseCustomEvents(
|
|
root: Element | Document,
|
|
history: IHistoryState[],
|
|
historyCurrentStep: number,
|
|
configuration: IConfiguration,
|
|
editorRef: React.RefObject<HTMLDivElement>,
|
|
setNewHistory: (newHistory: IHistoryState[], historyCurrentStep?: number) => void
|
|
): void {
|
|
useEffect(() => {
|
|
const editorState: IEditorState = {
|
|
history,
|
|
historyCurrentStep,
|
|
configuration
|
|
};
|
|
|
|
const funcs = new Map<string, () => void>();
|
|
for (const event of events) {
|
|
function Func(eventInitDict?: CustomEventInit): void {
|
|
return event.func({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
});
|
|
}
|
|
editorRef.current?.addEventListener(event.name, Func);
|
|
funcs.set(event.name, Func);
|
|
}
|
|
return () => {
|
|
for (const event of events) {
|
|
const func = funcs.get(event.name);
|
|
if (func === undefined) {
|
|
continue;
|
|
}
|
|
editorRef.current?.removeEventListener(event.name, func);
|
|
}
|
|
};
|
|
});
|
|
}
|
|
|
|
export function UseEditorListener(
|
|
root: Element | Document,
|
|
history: IHistoryState[],
|
|
historyCurrentStep: number,
|
|
configuration: IConfiguration
|
|
): void {
|
|
useEffect(() => {
|
|
const editorState: IEditorState = {
|
|
history,
|
|
historyCurrentStep,
|
|
configuration
|
|
};
|
|
const event = new CustomEvent('editorListener', { detail: editorState });
|
|
root.dispatchEvent(event);
|
|
});
|
|
}
|
|
|
|
function GetEditorState({
|
|
root,
|
|
editorState
|
|
}: IEditorEventParams): void {
|
|
const customEvent = new CustomEvent<IEditorState>('getEditorState', { detail: structuredClone(editorState) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function GetEditorStateAsString({
|
|
root,
|
|
editorState
|
|
}: IEditorEventParams): void {
|
|
const spaces = import.meta.env.DEV ? 4 : 0;
|
|
const data = JSON.stringify(editorState, GetCircularReplacer(), spaces);
|
|
const customEvent = new CustomEvent<string>('getEditorStateAsString', { detail: data });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function SetHistory({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const history: IHistoryState[] = eventInitDict?.detail.history;
|
|
const historyCurrentStep: number | undefined = eventInitDict?.detail.historyCurrentStep;
|
|
setNewHistory(history, historyCurrentStep);
|
|
const customEvent = new CustomEvent<IEditorState>('setHistory', { detail: editorState });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function GetCurrentHistoryState({
|
|
root,
|
|
editorState
|
|
}: IEditorEventParams): void {
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'getCurrentHistoryState',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function AppendNewState({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const state: IHistoryState = eventInitDict?.detail.state;
|
|
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
|
|
|
|
history.push(state);
|
|
setNewHistory(history);
|
|
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'appendNewState',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function AddContainer({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const {
|
|
index,
|
|
type,
|
|
parentId
|
|
} = eventInitDict?.detail;
|
|
|
|
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
|
|
const newHistory = AddContainerAction(
|
|
index,
|
|
type,
|
|
parentId,
|
|
editorState.configuration,
|
|
history,
|
|
editorState.historyCurrentStep
|
|
);
|
|
setNewHistory(newHistory);
|
|
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'addContainer',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function AddContainerToSelectedContainer({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const {
|
|
index,
|
|
type
|
|
} = eventInitDict?.detail;
|
|
|
|
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
|
|
const currentState = history[editorState.historyCurrentStep];
|
|
|
|
const newHistory = AddContainerAction(
|
|
index,
|
|
type,
|
|
currentState.selectedContainerId,
|
|
editorState.configuration,
|
|
history,
|
|
editorState.historyCurrentStep
|
|
);
|
|
setNewHistory(newHistory);
|
|
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'addContainerToSelectedContainer',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function AppendContainer({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const {
|
|
type,
|
|
parentId
|
|
} = eventInitDict?.detail;
|
|
|
|
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
|
|
const currentState = history[editorState.historyCurrentStep];
|
|
|
|
const parent = FindContainerById(currentState.containers, parentId);
|
|
|
|
const newHistory = AddContainerAction(
|
|
parent?.children.length ?? 0,
|
|
type,
|
|
parentId,
|
|
editorState.configuration,
|
|
history,
|
|
editorState.historyCurrentStep
|
|
);
|
|
setNewHistory(newHistory);
|
|
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'appendContainerToSelectedContainer',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function AppendContainerToSelectedContainer({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const {
|
|
type
|
|
} = eventInitDict?.detail;
|
|
|
|
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
|
|
const currentState = history[editorState.historyCurrentStep];
|
|
|
|
const selected = FindContainerById(currentState.containers, currentState.selectedContainerId);
|
|
|
|
if (selected !== null && selected !== undefined) {
|
|
setNewHistory(AddContainerToSelectedContainerAction(
|
|
type,
|
|
selected,
|
|
editorState.configuration,
|
|
history,
|
|
editorState.historyCurrentStep
|
|
));
|
|
}
|
|
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'appendContainerToSelectedContainer',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function SelectContainer({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const {
|
|
containerId
|
|
} = eventInitDict?.detail;
|
|
|
|
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
|
|
|
|
const newHistory = SelectContainerAction(
|
|
containerId,
|
|
history,
|
|
editorState.historyCurrentStep
|
|
);
|
|
setNewHistory(newHistory);
|
|
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'selectContainer',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function DeleteContainer({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const {
|
|
containerId
|
|
} = eventInitDict?.detail;
|
|
|
|
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
|
|
|
|
const newHistory = DeleteContainerAction(
|
|
containerId,
|
|
history,
|
|
editorState.historyCurrentStep
|
|
);
|
|
setNewHistory(newHistory);
|
|
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'deleteContainer',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function AddSymbol({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const {
|
|
name
|
|
} = eventInitDict?.detail;
|
|
|
|
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
|
|
|
|
const newHistory = AddSymbolAction(
|
|
name,
|
|
editorState.configuration,
|
|
history,
|
|
editorState.historyCurrentStep
|
|
);
|
|
setNewHistory(newHistory);
|
|
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'AddSymbol',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function SelectSymbol({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const {
|
|
symbolId
|
|
} = eventInitDict?.detail;
|
|
|
|
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
|
|
|
|
const newHistory = SelectSymbolAction(
|
|
symbolId,
|
|
history,
|
|
editorState.historyCurrentStep
|
|
);
|
|
setNewHistory(newHistory);
|
|
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'SelectSymbol',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|
|
|
|
function DeleteSymbol({
|
|
root,
|
|
editorState,
|
|
setNewHistory,
|
|
eventInitDict
|
|
}: IEditorEventParams): void {
|
|
const {
|
|
symbolId
|
|
} = eventInitDict?.detail;
|
|
|
|
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
|
|
const newHistory = DeleteSymbolAction(
|
|
symbolId,
|
|
history,
|
|
editorState.historyCurrentStep
|
|
);
|
|
setNewHistory(newHistory);
|
|
|
|
const customEvent = new CustomEvent<IHistoryState>(
|
|
'DeleteSymbol',
|
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
|
root.dispatchEvent(customEvent);
|
|
}
|