Move selectedContainerId and selectedSymbolId to Editor component

This commit is contained in:
Eric NGUYEN 2023-02-24 14:18:53 +01:00
parent f74405f002
commit c725b107a4
11 changed files with 165 additions and 252 deletions

View file

@ -1,30 +1,24 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace SVGLDLibs.Models
{
[DataContract]
public class HistoryState
{
[DataMember(EmitDefaultValue = false)]
public string lastAction;
[DataMember(EmitDefaultValue = false)]
public string mainContainer;
[DataMember(EmitDefaultValue = false)]
public Dictionary<string, ContainerModel> containers;
[DataMember(EmitDefaultValue = false)]
public string selectedContainerId;
[DataMember(EmitDefaultValue = false)]
public Dictionary<string, string> typeCounters;
[DataMember(EmitDefaultValue = false)]
public Dictionary<string, SymbolModel> symbols;
[DataMember(EmitDefaultValue = false)]
public string selectedSymbolId;
}
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace SVGLDLibs.Models
{
[DataContract]
public class HistoryState
{
[DataMember(EmitDefaultValue = false)]
public string lastAction;
[DataMember(EmitDefaultValue = false)]
public string mainContainer;
[DataMember(EmitDefaultValue = false)]
public Dictionary<string, ContainerModel> containers;
[DataMember(EmitDefaultValue = false)]
public Dictionary<string, string> typeCounters;
[DataMember(EmitDefaultValue = false)]
public Dictionary<string, SymbolModel> symbols;
}
}

View file

@ -102,12 +102,10 @@ describe.concurrent('Models test suite', () => {
lastAction: 'string',
mainContainer: mainContainer.properties.id,
containers,
selectedContainerId: '3',
typeCounters: {
main: 1
},
symbols: new Map(),
selectedSymbolId: ''
symbols: new Map()
};
it('ApplicationStateModel', async() => {

View file

@ -59,10 +59,8 @@ export function App(props: IAppProps): JSX.Element {
lastAction: '',
mainContainer: defaultMainContainer.properties.id,
containers,
selectedContainerId: defaultMainContainer.properties.id,
typeCounters: {},
symbols: new Map(),
selectedSymbolId: ''
symbols: new Map()
}],
historyCurrentStep: 0
});

View file

@ -100,11 +100,9 @@ export function AddContainers(
history.push({
lastAction: `Add [${containersIds.join(', ')}] in ${parentClone.properties.id}`,
mainContainer: current.mainContainer,
selectedContainerId: parentClone.properties.id,
containers,
typeCounters: newCounters,
symbols: structuredClone(current.symbols),
selectedSymbolId: current.selectedSymbolId
symbols: structuredClone(current.symbols)
});
return {

View file

@ -11,33 +11,6 @@ import { Orientation } from '../../../Enums/Orientation';
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
import { AddContainers } from './AddContainer';
/**
* Select a container
* @returns New history
* @param containerId
* @param fullHistory
* @param historyCurrentStep
*/
export function SelectContainer(
containerId: string,
fullHistory: IHistoryState[],
historyCurrentStep: number
): IHistoryState[] {
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
const current = history[history.length - 1];
history.push({
lastAction: `Select ${containerId}`,
mainContainer: current.mainContainer,
containers: structuredClone(current.containers),
selectedContainerId: containerId,
typeCounters: Object.assign({}, current.typeCounters),
symbols: structuredClone(current.symbols),
selectedSymbolId: current.selectedSymbolId
});
return history;
}
/**
* Deselect a container
* @returns New history
@ -54,10 +27,8 @@ export function DeselectContainer(
lastAction: `Deselect ${containerId}`,
mainContainer: current.mainContainer,
containers: structuredClone(current.containers),
selectedContainerId: 'undefined',
typeCounters: Object.assign({}, current.typeCounters),
symbols: structuredClone(current.symbols),
selectedSymbolId: current.selectedSymbolId
symbols: structuredClone(current.symbols)
});
return history;
}
@ -116,23 +87,12 @@ export function DeleteContainer(
ApplyBehaviorsOnSiblings(containers, container, current.symbols);
// Select the previous container
// or select the one above
const selectedContainerId = GetSelectedContainerOnDelete(
containers,
current.selectedContainerId,
parent,
index
);
history.push({
lastAction: `Delete ${containerId}`,
mainContainer: current.mainContainer,
containers,
selectedContainerId,
typeCounters: Object.assign({}, current.typeCounters),
symbols: newSymbols,
selectedSymbolId: current.selectedSymbolId
symbols: newSymbols
});
return history;
}
@ -182,10 +142,8 @@ export function ReplaceByContainer(
lastAction: `Replace ${containerId} by ${newContainerId}`,
mainContainer: currentDelete.mainContainer,
containers: currentDelete.containers,
selectedContainerId: currentDelete.selectedContainerId,
typeCounters: Object.assign({}, currentDelete.typeCounters),
symbols: current.symbols,
selectedSymbolId: current.selectedSymbolId
symbols: current.symbols
});
return fullHistory;
@ -276,10 +234,8 @@ export function OnPropertyChange(
lastAction: `Change ${key} of ${container.properties.id}`,
mainContainer: current.mainContainer,
containers,
selectedContainerId: container.properties.id,
typeCounters: Object.assign({}, current.typeCounters),
symbols: structuredClone(current.symbols),
selectedSymbolId: current.selectedSymbolId
symbols: structuredClone(current.symbols)
});
return history;
}

View file

@ -45,10 +45,8 @@ export function AddSymbol(
lastAction: `Add ${name}`,
mainContainer: current.mainContainer,
containers,
selectedContainerId: current.selectedContainerId,
typeCounters,
symbols: newSymbols,
selectedSymbolId: newSymbol.id
symbols: newSymbols
});
if (symbolConfig.AssociatedContainer !== undefined) {
@ -76,26 +74,6 @@ export function AddSymbol(
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: current.mainContainer,
containers: structuredClone(current.containers),
selectedContainerId: current.selectedContainerId,
typeCounters: structuredClone(current.typeCounters),
symbols: structuredClone(current.symbols),
selectedSymbolId: symbolId
});
return history;
}
export function DeleteSymbol(
symbolId: string,
fullHistory: IHistoryState[],
@ -120,10 +98,8 @@ export function DeleteSymbol(
lastAction: `Select ${symbolId}`,
mainContainer: current.mainContainer,
containers,
selectedContainerId: current.selectedContainerId,
typeCounters: structuredClone(current.typeCounters),
symbols: newSymbols,
selectedSymbolId: symbolId
symbols: newSymbols
});
return history;
}
@ -154,18 +130,19 @@ function UnlinkSymbolFromContainers(containers: Map<string, IContainerModel>, sy
export function OnPropertyChange(
key: string,
value: string | number | boolean,
selectedSymbolId: string,
fullHistory: IHistoryState[],
historyCurrentStep: number
): IHistoryState[] {
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
const current = history[history.length - 1];
if (current.selectedSymbolId === '') {
if (selectedSymbolId === '') {
throw new Error('[OnSymbolPropertyChange] Property was changed before selecting a symbol');
}
const newSymbols: Map<string, ISymbolModel> = structuredClone(current.symbols);
const symbol = newSymbols.get(current.selectedSymbolId);
const symbol = newSymbols.get(selectedSymbolId);
if (symbol === null || symbol === undefined) {
throw new Error('[OnSymbolPropertyChange] Symbol model was not found in state!');
@ -190,10 +167,8 @@ export function OnPropertyChange(
lastAction: `Change ${key} of ${symbol.id}`,
mainContainer: current.mainContainer,
containers,
selectedContainerId: current.selectedContainerId,
typeCounters: Object.assign({}, current.typeCounters),
symbols: newSymbols,
selectedSymbolId: symbol.id
symbols: newSymbols
});
return history;
}

View file

@ -8,14 +8,13 @@ import { MAX_HISTORY } from '../../utils/default';
import { FindContainerById } from '../../utils/itertools';
import { Menu } from '../Menu/Menu';
import { type IReplaceContainer } from '../../Interfaces/IReplaceContainer';
import { SelectContainer, DeleteContainer, OnPropertyChange, ReplaceByContainer } from './Actions/ContainerOperations';
import { DeleteContainer, OnPropertyChange, ReplaceByContainer } from './Actions/ContainerOperations';
import { SaveEditorAsJSON, SaveEditorAsSVG } from './Actions/Save';
import { OnKey } from './Actions/Shortcuts';
import {
AddSymbol,
OnPropertyChange as OnSymbolPropertyChange,
DeleteSymbol,
SelectSymbol
DeleteSymbol
} from './Actions/SymbolOperations';
import { InitActions } from './Actions/ContextMenuActions';
import { AddContainerToSelectedContainer, AddContainer } from './Actions/AddContainer';
@ -80,6 +79,8 @@ export function Editor(props: IEditorProps): JSX.Element {
replaceContainer,
setReplaceContainer
] = React.useState<IReplaceContainer>({ isReplacing: false, id: undefined, category: undefined });
const [selectedContainerId, setSelectedContainerId] = React.useState('');
const [selectedSymbolId, setSelectedSymbolId] = React.useState('');
const editorRef = useRef<HTMLDivElement>(null);
const setNewHistory = UseNewHistoryState(setHistory, setHistoryCurrentStep);
@ -94,8 +95,7 @@ export function Editor(props: IEditorProps): JSX.Element {
historyCurrentStep,
setHistoryCurrentStep,
() => {
const current = GetCurrentHistoryState(history, historyCurrentStep);
setNewHistory(DeleteContainer(current.selectedContainerId, history, historyCurrentStep));
setNewHistory(DeleteContainer(selectedContainerId, history, historyCurrentStep));
},
ResetState
);
@ -129,7 +129,7 @@ export function Editor(props: IEditorProps): JSX.Element {
// Render
const configuration = props.configuration;
const current = GetCurrentHistoryState(history, historyCurrentStep);
const selected = FindContainerById(current.containers, current.selectedContainerId);
const selected = FindContainerById(current.containers, selectedContainerId);
return (
<div ref={editorRef} className="Editor font-sans h-full ">
@ -140,12 +140,10 @@ export function Editor(props: IEditorProps): JSX.Element {
historyCurrentStep
}}
replaceContainer={replaceContainer}
selectedContainerId={selectedContainerId}
selectedSymbolId={selectedSymbolId}
selectContainer={(container) => {
setNewHistory(SelectContainer(
container,
history,
historyCurrentStep
));
setSelectedContainerId(container);
}}
deleteContainer={(containerId: string) => {
setNewHistory(DeleteContainer(
@ -210,16 +208,13 @@ export function Editor(props: IEditorProps): JSX.Element {
setNewHistory(OnSymbolPropertyChange(
key,
value,
selectedSymbolId,
history,
historyCurrentStep
));
}}
selectSymbol={(symbolId) => {
setNewHistory(SelectSymbol(
symbolId,
history,
historyCurrentStep
));
setSelectedSymbolId(symbolId);
}}
deleteSymbol={(symbolId) => {
setNewHistory(DeleteSymbol(

View file

@ -23,6 +23,8 @@ import { UseWorker, UseAsync } from './UseWorker';
export interface IUIProps {
editorState: IEditorState
replaceContainer: IReplaceContainer
selectedContainerId: string
selectedSymbolId: string
selectContainer: (containerId: string) => void
deleteContainer: (containerId: string) => void
onPropertyChange: (key: string, value: string | number | boolean | number[], type?: PropertyType) => void
@ -67,7 +69,14 @@ function UseSetOrToggleSidebar(
};
}
export function UI({ editorState, replaceContainer, setReplaceContainer, ...methods }: IUIProps): JSX.Element {
export function UI({
editorState,
replaceContainer,
selectedContainerId,
selectedSymbolId,
setReplaceContainer,
...methods
}: IUIProps): JSX.Element {
const [selectedSidebar, setSelectedSidebar] = React.useState<SidebarType>(SidebarType.Components);
const [
selectedExtendedSidebar,
@ -107,8 +116,8 @@ export function UI({ editorState, replaceContainer, setReplaceContainer, ...meth
throw new Error('Tried to initialized UI but there is no main container!');
}
const selectedContainer = FindContainerById(current.containers, current.selectedContainerId);
const selectedSymbol = current.symbols.get(current.selectedSymbolId);
const selectedContainer = FindContainerById(current.containers, selectedContainerId);
const selectedSymbol = current.symbols.get(selectedSymbolId);
switch (selectedSidebar) {
case SidebarType.Components:
@ -143,7 +152,7 @@ export function UI({ editorState, replaceContainer, setReplaceContainer, ...meth
/>;
rightSidebarTitle = Text({ textId: '@SymbolsRight' });
rightChildren = <SymbolsSidebar
selectedSymbolId={current.selectedSymbolId}
selectedSymbolId={selectedSymbolId}
symbols={current.symbols}
onPropertyChange={methods.onSymbolPropertyChange}
selectSymbol={methods.selectSymbol}

View file

@ -4,13 +4,11 @@ import {
AddContainerToSelectedContainer as AddContainerToSelectedContainerAction
} from '../Components/Editor/Actions/AddContainer';
import {
DeleteContainer as DeleteContainerAction,
SelectContainer as SelectContainerAction
DeleteContainer as DeleteContainerAction
} from '../Components/Editor/Actions/ContainerOperations';
import {
AddSymbol as AddSymbolAction,
DeleteSymbol as DeleteSymbolAction,
SelectSymbol as SelectSymbolAction
DeleteSymbol as DeleteSymbolAction
} from '../Components/Editor/Actions/SymbolOperations';
import { GetCurrentHistory } from '../Components/Editor/Editor';
import { type IConfiguration } from '../Interfaces/IConfiguration';
@ -37,13 +35,13 @@ export const events: IEditorEvent[] = [
{ name: 'getCurrentHistoryState', func: GetCurrentHistoryState },
{ name: 'appendNewState', func: AppendNewState },
{ name: 'addContainer', func: AddContainer },
{ name: 'addContainerToSelectedContainer', func: AddContainerToSelectedContainer },
// { name: 'addContainerToSelectedContainer', func: AddContainerToSelectedContainer },
{ name: 'appendContainer', func: AppendContainer },
{ name: 'appendContainerToSelectedContainer', func: AppendContainerToSelectedContainer },
{ name: 'selectContainer', func: SelectContainer },
// { name: 'appendContainerToSelectedContainer', func: AppendContainerToSelectedContainer },
// { name: 'selectContainer', func: SelectContainer },
{ name: 'deleteContainer', func: DeleteContainer },
{ name: 'addSymbol', func: AddSymbol },
{ name: 'selectSymbol', func: SelectSymbol },
// { name: 'selectSymbol', func: SelectSymbol },
{ name: 'deleteSymbol', func: DeleteSymbol }
];
@ -203,36 +201,36 @@ function AddContainer({
root.dispatchEvent(customEvent);
}
function AddContainerToSelectedContainer({
root,
editorState,
setNewHistory,
eventInitDict
}: IEditorEventParams): void {
const {
index,
type
} = eventInitDict?.detail;
// 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 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 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);
}
// const customEvent = new CustomEvent<IHistoryState>(
// 'addContainerToSelectedContainer',
// { detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
// );
// root.dispatchEvent(customEvent);
// }
function AppendContainer({
root,
@ -267,63 +265,63 @@ function AppendContainer({
root.dispatchEvent(customEvent);
}
function AppendContainerToSelectedContainer({
root,
editorState,
setNewHistory,
eventInitDict
}: IEditorEventParams): void {
const {
type
} = eventInitDict?.detail;
// 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 history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
// const currentState = history[editorState.historyCurrentStep];
const selected = FindContainerById(currentState.containers, currentState.selectedContainerId);
// const selected = FindContainerById(currentState.containers, currentState.selectedContainerId);
if (selected !== null && selected !== undefined) {
setNewHistory(AddContainerToSelectedContainerAction(
type,
selected,
editorState.configuration,
history,
editorState.historyCurrentStep
));
}
// 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);
}
// 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;
// function SelectContainer({
// root,
// editorState,
// setNewHistory,
// eventInitDict
// }: IEditorEventParams): void {
// const {
// containerId
// } = eventInitDict?.detail;
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
// const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
const newHistory = SelectContainerAction(
containerId,
history,
editorState.historyCurrentStep
);
setNewHistory(newHistory);
// const newHistory = SelectContainerAction(
// containerId,
// history,
// editorState.historyCurrentStep
// );
// setNewHistory(newHistory);
const customEvent = new CustomEvent<IHistoryState>(
'selectContainer',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
// const customEvent = new CustomEvent<IHistoryState>(
// 'selectContainer',
// { detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
// );
// root.dispatchEvent(customEvent);
// }
function DeleteContainer({
root,
@ -378,31 +376,31 @@ function AddSymbol({
root.dispatchEvent(customEvent);
}
function SelectSymbol({
root,
editorState,
setNewHistory,
eventInitDict
}: IEditorEventParams): void {
const {
symbolId
} = eventInitDict?.detail;
// function SelectSymbol({
// root,
// editorState,
// setNewHistory,
// eventInitDict
// }: IEditorEventParams): void {
// const {
// symbolId
// } = eventInitDict?.detail;
const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
// const history = GetCurrentHistory(editorState.history, editorState.historyCurrentStep);
const newHistory = SelectSymbolAction(
symbolId,
history,
editorState.historyCurrentStep
);
setNewHistory(newHistory);
// const newHistory = SelectSymbolAction(
// symbolId,
// history,
// editorState.historyCurrentStep
// );
// setNewHistory(newHistory);
const customEvent = new CustomEvent<IHistoryState>(
'SelectSymbol',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
// const customEvent = new CustomEvent<IHistoryState>(
// 'SelectSymbol',
// { detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
// );
// root.dispatchEvent(customEvent);
// }
function DeleteSymbol({
root,

View file

@ -13,15 +13,9 @@ export interface IHistoryState {
// TODO: Update addContainers and deleteContainer to update the hashmap
containers: Map<string, IContainerModel>
/** Id of the selected container */
selectedContainerId: string
/** Counter of type of container. Used for ids. */
typeCounters: Record<string, number>
/** List of symbols */
symbols: Map<string, ISymbolModel>
/** Selected symbols id */
selectedSymbolId: string
}

View file

@ -147,10 +147,8 @@ export function GetDefaultEditorState(configuration: IConfiguration): IEditorSta
lastAction: '',
mainContainer: mainContainer.properties.id,
containers,
selectedContainerId: mainContainer.properties.id,
typeCounters,
symbols: new Map(),
selectedSymbolId: ''
symbols: new Map()
}
],
historyCurrentStep: 0