svg-layout-designer-react/src/Events/EditorEvents.ts
2022-11-04 13:52:40 +01:00

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