Merged PR 173: Implements API methods through right click + more (read desc)

- 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
This commit is contained in:
Eric Nguyen 2022-08-30 14:45:29 +00:00
parent 79c6874240
commit 57e6c9a156
20 changed files with 652 additions and 291 deletions

View file

@ -4,15 +4,16 @@ import { IConfiguration } from '../../Interfaces/IConfiguration';
import { SVG } from '../SVG/SVG';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { UI } from '../UI/UI';
import { SelectContainer, DeleteContainer, AddContainerToSelectedContainer, OnPropertyChange } from './Actions/ContainerOperations';
import { SelectContainer, DeleteContainer, AddContainerToSelectedContainer, OnPropertyChange, AddContainers } from './Actions/ContainerOperations';
import { SaveEditorAsJSON, SaveEditorAsSVG } from './Actions/Save';
import { OnKey } from './Actions/Shortcuts';
import EditorEvents from '../../Events/EditorEvents';
import { events as EVENTS } from '../../Events/EditorEvents';
import { IEditorState } from '../../Interfaces/IEditorState';
import { MAX_HISTORY } from '../../utils/default';
import { AddSymbol, OnPropertyChange as OnSymbolPropertyChange, DeleteSymbol, SelectSymbol } from './Actions/SymbolOperations';
import { FindContainerById } from '../../utils/itertools';
import { Menu } from '../Menu/Menu';
import { IMenuAction, Menu } from '../Menu/Menu';
import { GetAction } from './Actions/ContextMenuActions';
interface IEditorProps {
root: Element | Document
@ -22,11 +23,11 @@ interface IEditorProps {
}
function InitActions(
menuActions: Map<any, any>,
menuActions: Map<string, IMenuAction[]>,
configuration: IConfiguration,
history: IHistoryState[],
historyCurrentStep: number,
setHistory: React.Dispatch<React.SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: React.Dispatch<React.SetStateAction<number>>
setNewHistory: (newHistory: IHistoryState[]) => void
): void {
menuActions.set(
'elements-sidebar-row',
@ -34,13 +35,12 @@ function InitActions(
text: 'Delete',
action: (target: HTMLElement) => {
const id = target.id;
DeleteContainer(
const newHistory = DeleteContainer(
id,
history,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
historyCurrentStep
);
setNewHistory(newHistory);
}
}]
);
@ -50,16 +50,43 @@ function InitActions(
text: 'Delete',
action: (target: HTMLElement) => {
const id = target.id;
DeleteSymbol(
const newHistory = DeleteSymbol(
id,
history,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
historyCurrentStep
);
setNewHistory(newHistory);
}
}]
);
// API Actions
for (const availableContainer of configuration.AvailableContainers) {
if (availableContainer.Actions === undefined) {
continue;
}
for (const action of availableContainer.Actions) {
if (menuActions.get(availableContainer.Type) === undefined) {
menuActions.set(availableContainer.Type, []);
}
const currentState = GetCurrentHistoryState(history, historyCurrentStep);
const newAction: IMenuAction = {
text: action.Label,
action: GetAction(
action,
currentState,
configuration,
history,
historyCurrentStep,
setNewHistory
)
};
menuActions.get(availableContainer.Type)?.push(newAction);
}
}
}
function UseShortcuts(
@ -90,11 +117,9 @@ function UseWindowEvents(
historyCurrentStep: number,
configuration: IConfiguration,
editorRef: React.RefObject<HTMLDivElement>,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
setNewHistory: (newHistory: IHistoryState[]) => void
): void {
useEffect(() => {
const events = EditorEvents;
const editorState: IEditorState = {
history,
historyCurrentStep,
@ -102,13 +127,12 @@ function UseWindowEvents(
};
const funcs = new Map<string, () => void>();
for (const event of events) {
for (const event of EVENTS) {
function Func(eventInitDict?: CustomEventInit): void {
return event.func(
root,
editorState,
setHistory,
setHistoryCurrentStep,
setNewHistory,
eventInitDict
);
}
@ -116,7 +140,7 @@ function UseWindowEvents(
funcs.set(event.name, Func);
}
return () => {
for (const event of events) {
for (const event of EVENTS) {
const func = funcs.get(event.name);
if (func === undefined) {
continue;
@ -127,11 +151,29 @@ function UseWindowEvents(
});
}
/**
* Return a macro function to use both setHistory
* and setHistoryCurrentStep at the same time
* @param setHistory
* @param setHistoryCurrentStep
* @returns
*/
function UseNewHistoryState(
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): (newHistory: IHistoryState[]) => void {
return (newHistory) => {
setHistory(newHistory);
setHistoryCurrentStep(newHistory.length - 1);
};
}
export function Editor(props: IEditorProps): JSX.Element {
// States
const [history, setHistory] = React.useState<IHistoryState[]>(structuredClone(props.history));
const [historyCurrentStep, setHistoryCurrentStep] = React.useState<number>(props.historyCurrentStep);
const editorRef = useRef<HTMLDivElement>(null);
const setNewHistory = UseNewHistoryState(setHistory, setHistoryCurrentStep);
// Events
UseShortcuts(history, historyCurrentStep, setHistoryCurrentStep);
@ -141,13 +183,18 @@ export function Editor(props: IEditorProps): JSX.Element {
historyCurrentStep,
props.configuration,
editorRef,
setHistory,
setHistoryCurrentStep
setNewHistory
);
// Context Menu
const menuActions = new Map();
InitActions(menuActions, history, historyCurrentStep, setHistory, setHistoryCurrentStep);
InitActions(
menuActions,
props.configuration,
history,
historyCurrentStep,
setNewHistory
);
// Render
const configuration = props.configuration;
@ -162,66 +209,62 @@ export function Editor(props: IEditorProps): JSX.Element {
historyCurrentStep={historyCurrentStep}
availableContainers={configuration.AvailableContainers}
availableSymbols={configuration.AvailableSymbols}
selectContainer={(container) => SelectContainer(
container,
history,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
)}
deleteContainer={(containerId: string) => DeleteContainer(
containerId,
history,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
)}
onPropertyChange={(key, value, type) => OnPropertyChange(
key, value, type,
selected,
history,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
)}
addContainer={(type) => AddContainerToSelectedContainer(
type,
selected,
configuration,
history,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
)}
addSymbol={(type) => AddSymbol(
type,
configuration,
history,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
)}
onSymbolPropertyChange={(key, value) => OnSymbolPropertyChange(
key, value,
history,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
)}
selectSymbol={(symbolId) => SelectSymbol(
symbolId,
history,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
)}
deleteSymbol={(symbolId) => DeleteSymbol(
symbolId,
history,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
)}
selectContainer={(container) => setNewHistory(
SelectContainer(
container,
history,
historyCurrentStep
))}
deleteContainer={(containerId: string) => setNewHistory(
DeleteContainer(
containerId,
history,
historyCurrentStep
))}
onPropertyChange={(key, value, type) => setNewHistory(
OnPropertyChange(
key, value, type,
selected,
history,
historyCurrentStep
))}
addContainer={(type) => {
const newHistory = AddContainerToSelectedContainer(
type,
selected,
configuration,
history,
historyCurrentStep
);
if (newHistory !== null) {
setNewHistory(newHistory);
}
}}
addSymbol={(type) => setNewHistory(
AddSymbol(
type,
configuration,
history,
historyCurrentStep
))}
onSymbolPropertyChange={(key, value) => setNewHistory(
OnSymbolPropertyChange(
key, value,
history,
historyCurrentStep
))}
selectSymbol={(symbolId) => setNewHistory(
SelectSymbol(
symbolId,
history,
historyCurrentStep
))}
deleteSymbol={(symbolId) => setNewHistory(
DeleteSymbol(
symbolId,
history,
historyCurrentStep
))}
saveEditorAsJSON={() => SaveEditorAsJSON(
history,
historyCurrentStep,