Implement events for external use + Rename interfaces with a I prefix + add some documentation (#26)
All checks were successful
continuous-integration/drone/push Build is passing

Implement events for external use
Rename interfaces with a I prefix
Add some documentation

Co-authored-by: Eric NGUYEN <enguyen@techform.fr>
Reviewed-on: https://git.siklos-chaneru.duckdns.org/Siklos/svg-layout-designer-react/pulls/26
This commit is contained in:
Siklos 2022-08-12 06:36:14 -04:00
parent 6c601429b9
commit c81a6fe44b
38 changed files with 228 additions and 116 deletions

View file

@ -1,7 +1,7 @@
import { Dispatch, SetStateAction } from 'react';
import { HistoryState } from '../../Interfaces/HistoryState';
import { Configuration } from '../../Interfaces/Configuration';
import { ContainerModel, IContainerModel } from '../../Interfaces/ContainerModel';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { IConfiguration } from '../../Interfaces/IConfiguration';
import { ContainerModel, IContainerModel } from '../../Interfaces/IContainerModel';
import { findContainerById } from '../../utils/itertools';
import { getCurrentHistory } from './Editor';
@ -11,9 +11,9 @@ import { getCurrentHistory } from './Editor';
*/
export function SelectContainer(
container: ContainerModel,
fullHistory: HistoryState[],
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep);
@ -46,9 +46,9 @@ export function SelectContainer(
*/
export function DeleteContainer(
containerId: string,
fullHistory: HistoryState[],
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep);
@ -108,10 +108,10 @@ export function DeleteContainer(
*/
export function AddContainerToSelectedContainer(
type: string,
configuration: Configuration,
fullHistory: HistoryState[],
configuration: IConfiguration,
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep);
@ -151,10 +151,10 @@ export function AddContainer(
index: number,
type: string,
parentId: string,
configuration: Configuration,
fullHistory: HistoryState[],
configuration: IConfiguration,
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep);

View file

@ -1,32 +1,29 @@
import React from 'react';
import React, { useRef } from 'react';
import './Editor.scss';
import { Configuration } from '../../Interfaces/Configuration';
import { IConfiguration } from '../../Interfaces/IConfiguration';
import { SVG } from '../SVG/SVG';
import { HistoryState } from '../../Interfaces/HistoryState';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { UI } from '../UI/UI';
import { SelectContainer, DeleteContainer, AddContainerToSelectedContainer, AddContainer } from './ContainerOperations';
import { SaveEditorAsJSON, SaveEditorAsSVG } from './Save';
import { onKeyDown } from './Shortcuts';
import { OnPropertyChange, OnPropertiesSubmit } from './PropertiesOperations';
import EditorEvents from '../../Events/EditorEvents';
import { IEditorState } from '../../Interfaces/IEditorState';
interface IEditorProps {
configuration: Configuration
history: HistoryState[]
configuration: IConfiguration
history: IHistoryState[]
historyCurrentStep: number
}
export interface IEditorState {
history: HistoryState[]
historyCurrentStep: number
configuration: Configuration
}
export const getCurrentHistory = (history: HistoryState[], historyCurrentStep: number): HistoryState[] => history.slice(0, historyCurrentStep + 1);
export const getCurrentHistoryState = (history: HistoryState[], historyCurrentStep: number): HistoryState => history[historyCurrentStep];
export const getCurrentHistory = (history: IHistoryState[], historyCurrentStep: number): IHistoryState[] => history.slice(0, historyCurrentStep + 1);
export const getCurrentHistoryState = (history: IHistoryState[], historyCurrentStep: number): IHistoryState => history[historyCurrentStep];
const Editor: React.FunctionComponent<IEditorProps> = (props) => {
const [history, setHistory] = React.useState<HistoryState[]>(structuredClone(props.history));
const [history, setHistory] = React.useState<IHistoryState[]>(structuredClone(props.history));
const [historyCurrentStep, setHistoryCurrentStep] = React.useState<number>(props.historyCurrentStep);
const editorRef = useRef<HTMLDivElement>(null);
React.useEffect(() => {
const onKeyUp = (event: KeyboardEvent): void => onKeyDown(
@ -38,6 +35,17 @@ const Editor: React.FunctionComponent<IEditorProps> = (props) => {
window.addEventListener('keyup', onKeyUp);
const events = EditorEvents;
const editorState: IEditorState = {
history,
historyCurrentStep,
configuration: props.configuration
};
for (const event of events) {
editorRef.current?.addEventListener(event.name, () => event.func(editorState));
}
return () => {
window.removeEventListener('keyup', onKeyUp);
};
@ -46,7 +54,7 @@ const Editor: React.FunctionComponent<IEditorProps> = (props) => {
const configuration = props.configuration;
const current = getCurrentHistoryState(history, historyCurrentStep);
return (
<div className="App font-sans h-full">
<div ref={editorRef} className="Editor font-sans h-full">
<UI
current={current}
history={history}

View file

@ -1,7 +1,7 @@
import { Dispatch, SetStateAction } from 'react';
import { IContainerModel, ContainerModel } from '../../Interfaces/ContainerModel';
import { HistoryState } from '../../Interfaces/HistoryState';
import Properties from '../../Interfaces/Properties';
import { IContainerModel, ContainerModel } from '../../Interfaces/IContainerModel';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import IProperties from '../../Interfaces/IProperties';
import { findContainerById } from '../../utils/itertools';
import { getCurrentHistory } from './Editor';
import { RecalculatePhysics } from './RigidBodyBehaviors';
@ -15,9 +15,9 @@ import { RecalculatePhysics } from './RigidBodyBehaviors';
export function OnPropertyChange(
key: string,
value: string | number | boolean,
fullHistory: HistoryState[],
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep);
@ -73,10 +73,10 @@ export function OnPropertyChange(
*/
export function OnPropertiesSubmit(
event: React.SyntheticEvent<HTMLFormElement>,
properties: Properties,
fullHistory: HistoryState[],
properties: IProperties,
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
event.preventDefault();

View file

@ -1,5 +1,5 @@
import { IContainerModel } from '../../Interfaces/ContainerModel';
import { SizePointer } from '../../Interfaces/SizePointer';
import { IContainerModel } from '../../Interfaces/IContainerModel';
import { ISizePointer } from '../../Interfaces/ISizePointer';
/**
* "Transform the container into a rigid body"
@ -167,17 +167,17 @@ function constraintBodyInsideUnallocatedWidth(
* (except the fact that disk space is divided by block).
* @param container Container where to find an available width
* @param exception Container to exclude of the widths (since a container will be moved, it might need to be excluded)
* @returns {SizePointer[]} Array of unallocated widths (x=position of the unallocated space, width=size of the allocated space)
* @returns {ISizePointer[]} Array of unallocated widths (x=position of the unallocated space, width=size of the allocated space)
*/
function getAvailableWidths(
container: IContainerModel,
exception: IContainerModel
): SizePointer[] {
): ISizePointer[] {
// Initialize the first size pointer
// which takes full width of the available space
const x = 0;
const width = Number(container.properties.width);
let unallocatedSpaces: SizePointer[] = [{ x, width }];
let unallocatedSpaces: ISizePointer[] = [{ x, width }];
// We will only uses containers that also have the rigid bodies
// as out-of-bound or enormouse containers should be ignored
@ -192,7 +192,7 @@ function getAvailableWidths(
}
// get the space of the child that is inside the parent
let newUnallocatedSpace: SizePointer[] = [];
let newUnallocatedSpace: ISizePointer[] = [];
// We will iterate on a mutable variable in order to divide it
for (const unallocatedSpace of unallocatedSpaces) {
@ -229,7 +229,7 @@ function getAvailableWidthsTwoLines(
max1: number,
min2: number,
max2: number
): SizePointer[] {
): ISizePointer[] {
if (min2 < min1 && max2 > max1) {
// object 2 is overlapping full width
return [];
@ -276,5 +276,5 @@ function getAvailableWidthsTwoLines(
*/
const isFitting = (
container: IContainerModel,
sizePointer: SizePointer
sizePointer: ISizePointer
): boolean => Number(container.properties.width) <= sizePointer.width;

View file

@ -1,13 +1,13 @@
import { HistoryState } from '../../Interfaces/HistoryState';
import { Configuration } from '../../Interfaces/Configuration';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { IConfiguration } from '../../Interfaces/IConfiguration';
import { getCircularReplacer } from '../../utils/saveload';
import { ID } from '../SVG/SVG';
import { IEditorState } from './Editor';
import { IEditorState } from '../../Interfaces/IEditorState';
export function SaveEditorAsJSON(
history: HistoryState[],
history: IHistoryState[],
historyCurrentStep: number,
configuration: Configuration
configuration: IConfiguration
): void {
const exportName = 'state';
const spaces = import.meta.env.DEV ? 4 : 0;

View file

@ -1,9 +1,9 @@
import { Dispatch, SetStateAction } from 'react';
import { HistoryState } from '../../Interfaces/HistoryState';
import { IHistoryState } from '../../Interfaces/IHistoryState';
export function onKeyDown(
event: KeyboardEvent,
history: HistoryState[],
history: IHistoryState[],
historyCurrentStep: number,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {