Merged PR 226: Implement associated container and default X, Y position for Symbol
Implement associated container and default X, Y position for Symbol Related work items: #7537, #7540
This commit is contained in:
parent
0a664752e9
commit
4ff2e0b7fb
9 changed files with 136 additions and 48 deletions
|
@ -7,13 +7,26 @@ namespace SVGLDLibs.Models
|
|||
{
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public ImageModel Image { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public PositionReferenceEnumModel PositionReference { get; set; }
|
||||
public double X { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public double Y { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public double Width { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public double Height { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public PositionReferenceEnumModel PositionReference { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public AvailableContainerModel AssociatedContainer { get; set; }
|
||||
}
|
||||
}
|
|
@ -8,16 +8,22 @@ namespace SVGLDLibs.Models
|
|||
{
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public string id { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public string type { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public AvailableSymbolModel config { get; set; }
|
||||
public AvailableSymbolModel config { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public double x { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public double width { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public double height { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public List<string> linkedContainers { get; set; }
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
|||
import { Orientation } from '../../../Enums/Orientation';
|
||||
import { GetDefaultContainerProps } from '../../../utils/default';
|
||||
import { FindContainerById } from '../../../utils/itertools';
|
||||
import { ApplyMargin, RestoreX, RestoreY, TransformX } from '../../../utils/svg';
|
||||
import { ApplyMargin, RestoreX, RestoreY } from '../../../utils/svg';
|
||||
import { ApplyBehaviors, ApplyBehaviorsOnSiblingsChildren } from '../Behaviors/Behaviors';
|
||||
import { GetCurrentHistory, UpdateCounters } from '../Editor';
|
||||
import { SortChildren } from './ContainerOperations';
|
||||
|
@ -59,7 +59,10 @@ export function AddContainers(
|
|||
configuration: IConfiguration,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
): {
|
||||
history: IHistoryState[]
|
||||
newContainers: IContainerModel[]
|
||||
} {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
|
@ -77,18 +80,27 @@ export function AddContainers(
|
|||
// Deep clone the counters
|
||||
const newCounters = Object.assign({}, current.typeCounters);
|
||||
|
||||
// containerIds is used for logging purpose (see setHistory below)
|
||||
const containerIds: string[] = [];
|
||||
|
||||
// Iterate over the containers
|
||||
const newContainers: IContainerModel[] = [];
|
||||
availableContainers.forEach((availableContainer, typeIndex) => {
|
||||
// Get the preset properties from the API
|
||||
AddNewContainerToParent(availableContainer, configuration, containers, parentClone, index, typeIndex, newCounters, current.symbols, containerIds);
|
||||
const newContainer = AddNewContainerToParent(
|
||||
availableContainer,
|
||||
configuration,
|
||||
containers,
|
||||
parentClone,
|
||||
index,
|
||||
typeIndex,
|
||||
newCounters,
|
||||
current.symbols
|
||||
);
|
||||
newContainers.push(newContainer);
|
||||
});
|
||||
|
||||
// Update the state
|
||||
const containersIds = newContainers.map(container => container.properties.id);
|
||||
history.push({
|
||||
lastAction: `Add [${containerIds.join(', ')}] in ${parentClone.properties.id}`,
|
||||
lastAction: `Add [${containersIds.join(', ')}] in ${parentClone.properties.id}`,
|
||||
mainContainer: current.mainContainer,
|
||||
selectedContainerId: parentClone.properties.id,
|
||||
containers,
|
||||
|
@ -97,7 +109,10 @@ export function AddContainers(
|
|||
selectedSymbolId: current.selectedSymbolId
|
||||
});
|
||||
|
||||
return history;
|
||||
return {
|
||||
history,
|
||||
newContainers
|
||||
};
|
||||
}
|
||||
|
||||
function AddNewContainerToParent(
|
||||
|
@ -109,7 +124,6 @@ function AddNewContainerToParent(
|
|||
typeIndex: number,
|
||||
newCounters: Record<string, number>,
|
||||
symbols: Map<string, ISymbolModel>,
|
||||
containerIds: string[] = [],
|
||||
initChilds: boolean = true
|
||||
): ContainerModel {
|
||||
const type = availableContainer.Type;
|
||||
|
@ -207,9 +221,6 @@ function AddNewContainerToParent(
|
|||
}
|
||||
}
|
||||
|
||||
// Add to the list of container id for logging purpose
|
||||
containerIds.push(newContainer.properties.id);
|
||||
|
||||
return newContainer;
|
||||
}
|
||||
|
||||
|
@ -234,7 +245,7 @@ export function AddContainer(
|
|||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
// just call AddContainers with an array on a single element
|
||||
return AddContainers(
|
||||
const { history } = AddContainers(
|
||||
index,
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
[{ Type: type }],
|
||||
|
@ -243,6 +254,7 @@ export function AddContainer(
|
|||
fullHistory,
|
||||
historyCurrentStep
|
||||
);
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -432,7 +444,6 @@ function AddContainerInLevel(
|
|||
0, 0,
|
||||
newCounters,
|
||||
symbols,
|
||||
undefined,
|
||||
false
|
||||
);
|
||||
|
||||
|
|
|
@ -282,11 +282,12 @@ function SetContainer(
|
|||
AssignProperty(container, key, value, type);
|
||||
|
||||
// link the symbol if it exists
|
||||
const oldSymbol = symbols.get(oldSymbolId);
|
||||
const newSymbol = symbols.get(container.properties.linkedSymbolId);
|
||||
LinkSymbol(
|
||||
container.properties.id,
|
||||
oldSymbolId,
|
||||
container.properties.linkedSymbolId,
|
||||
symbols
|
||||
oldSymbol,
|
||||
newSymbol
|
||||
);
|
||||
|
||||
// Apply special behaviors: rigid, flex, symbol, anchor
|
||||
|
@ -357,15 +358,11 @@ function AssignProperty(container: ContainerModel, key: string, value: string |
|
|||
* @param symbols Current list of symbols
|
||||
* @returns
|
||||
*/
|
||||
function LinkSymbol(
|
||||
export function LinkSymbol(
|
||||
containerId: string,
|
||||
oldSymbolId: string,
|
||||
newSymbolId: string,
|
||||
symbols: Map<string, ISymbolModel>
|
||||
oldSymbol: ISymbolModel | undefined,
|
||||
newSymbol: ISymbolModel | undefined
|
||||
): void {
|
||||
const oldSymbol = symbols.get(oldSymbolId);
|
||||
const newSymbol = symbols.get(newSymbolId);
|
||||
|
||||
if (newSymbol === undefined) {
|
||||
if (oldSymbol !== undefined) {
|
||||
oldSymbol.linkedContainers.delete(containerId);
|
||||
|
|
|
@ -203,20 +203,21 @@ function HandleSetContainerList(
|
|||
const containers = current.containers;
|
||||
switch (addingBehavior) {
|
||||
case AddMethod.Insert:
|
||||
case AddMethod.Append:
|
||||
case AddMethod.Append: {
|
||||
response.Containers.forEach(config => {
|
||||
config.AddMethod = config.AddMethod ?? addingBehavior;
|
||||
});
|
||||
setNewHistory(
|
||||
AddContainers(
|
||||
selectedContainer.children.length,
|
||||
response.Containers,
|
||||
selectedContainer.properties.id,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep
|
||||
));
|
||||
const { history: newHistory } = AddContainers(
|
||||
selectedContainer.children.length,
|
||||
response.Containers,
|
||||
selectedContainer.properties.id,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep);
|
||||
|
||||
setNewHistory(newHistory);
|
||||
break;
|
||||
}
|
||||
case AddMethod.Replace:
|
||||
setNewHistory(
|
||||
HandleReplace(
|
||||
|
@ -275,7 +276,7 @@ function HandleReplace(
|
|||
historyCurrentStep
|
||||
);
|
||||
|
||||
const newHistoryBeforeDelete = AddContainers(
|
||||
const { history: newHistoryBeforeDelete } = AddContainers(
|
||||
index,
|
||||
response.Containers,
|
||||
selectedContainer.properties.parentId,
|
||||
|
@ -318,7 +319,7 @@ function HandleInsert(
|
|||
historyCurrentStep
|
||||
);
|
||||
|
||||
const newHistoryBeforeDelete = AddContainers(
|
||||
const { history: newHistoryBeforeDelete } = AddContainers(
|
||||
index,
|
||||
response.Containers,
|
||||
selectedContainer.properties.parentId,
|
||||
|
|
|
@ -6,7 +6,9 @@ import { GetDefaultSymbolModel } from '../../../utils/default';
|
|||
import { FindContainerById } from '../../../utils/itertools';
|
||||
import { RestoreX } from '../../../utils/svg';
|
||||
import { ApplyBehaviors, ApplyBehaviorsOnSiblingsChildren } from '../Behaviors/Behaviors';
|
||||
import { GetCurrentHistory, UpdateCounters } from '../Editor';
|
||||
import { GetCurrentHistory, GetCurrentHistoryState, UpdateCounters } from '../Editor';
|
||||
import { AddContainers } from './AddContainer';
|
||||
import { LinkSymbol } from './ContainerOperations';
|
||||
|
||||
export function AddSymbol(
|
||||
name: string,
|
||||
|
@ -14,7 +16,7 @@ export function AddSymbol(
|
|||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
let history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
const symbolConfig = configuration.AvailableSymbols
|
||||
|
@ -24,24 +26,48 @@ export function AddSymbol(
|
|||
throw new Error('[AddSymbol] Symbol could not be found in the config');
|
||||
}
|
||||
const type = `symbol-${name}`;
|
||||
const newCounters = structuredClone(current.typeCounters);
|
||||
UpdateCounters(newCounters, type);
|
||||
const typeCounters = structuredClone(current.typeCounters);
|
||||
UpdateCounters(typeCounters, type);
|
||||
|
||||
const newSymbols = structuredClone(current.symbols);
|
||||
const newSymbol: ISymbolModel = GetDefaultSymbolModel(name, newCounters, type, symbolConfig);
|
||||
const newSymbol: ISymbolModel = GetDefaultSymbolModel(name, typeCounters, type, symbolConfig);
|
||||
const containers = structuredClone(current.containers);
|
||||
newSymbol.x = RestoreX(newSymbol.x, newSymbol.width, newSymbol.config.PositionReference);
|
||||
|
||||
newSymbols.set(newSymbol.id, newSymbol);
|
||||
|
||||
history.push({
|
||||
lastAction: `Add ${name}`,
|
||||
mainContainer: structuredClone(current.mainContainer),
|
||||
containers: structuredClone(current.containers),
|
||||
mainContainer: current.mainContainer,
|
||||
containers,
|
||||
selectedContainerId: current.selectedContainerId,
|
||||
typeCounters: newCounters,
|
||||
typeCounters,
|
||||
symbols: newSymbols,
|
||||
selectedSymbolId: newSymbol.id
|
||||
});
|
||||
|
||||
if (symbolConfig.AssociatedContainer !== undefined) {
|
||||
const {
|
||||
history: newHistory,
|
||||
newContainers
|
||||
} = AddContainers(
|
||||
0,
|
||||
[symbolConfig.AssociatedContainer],
|
||||
current.mainContainer,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep + 1
|
||||
);
|
||||
|
||||
history = newHistory;
|
||||
const newCurrent = GetCurrentHistoryState(newHistory, historyCurrentStep + 2);
|
||||
const newerSymbol = newCurrent.symbols.get(newSymbol.id);
|
||||
|
||||
newContainers.forEach((newContainer) => {
|
||||
LinkContainer(newerSymbol, newContainer, newSymbols);
|
||||
});
|
||||
}
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
|
@ -55,7 +81,7 @@ export function SelectSymbol(
|
|||
|
||||
history.push({
|
||||
lastAction: `Select ${symbolId}`,
|
||||
mainContainer: structuredClone(current.mainContainer),
|
||||
mainContainer: current.mainContainer,
|
||||
containers: structuredClone(current.containers),
|
||||
selectedContainerId: current.selectedContainerId,
|
||||
typeCounters: structuredClone(current.typeCounters),
|
||||
|
@ -166,3 +192,20 @@ export function OnPropertyChange(
|
|||
});
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a container to a symbol.
|
||||
* If symbol is undefined, unlink the previous symbol of the container
|
||||
* @param symbol
|
||||
* @param container
|
||||
* @param symbols
|
||||
*/
|
||||
function LinkContainer(
|
||||
symbol: ISymbolModel | undefined,
|
||||
container: IContainerModel,
|
||||
symbols: Map<string, ISymbolModel>
|
||||
): void {
|
||||
const oldSymbol = symbols.get(container.properties.linkedSymbolId);
|
||||
LinkSymbol(container.properties.id, oldSymbol, symbol);
|
||||
container.properties.linkedSymbolId = symbol !== undefined ? symbol.id : '';
|
||||
}
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { PositionReference } from '../Enums/PositionReference';
|
||||
import { IAvailableContainer } from './IAvailableContainer';
|
||||
import { IImage } from './IImage';
|
||||
|
||||
/**
|
||||
* Model of available symbol to configure the application */
|
||||
export interface IAvailableSymbol {
|
||||
Name: string
|
||||
|
||||
Image: IImage
|
||||
|
||||
X?: number
|
||||
|
||||
Y?: number
|
||||
|
||||
Width?: number
|
||||
|
||||
Height?: number
|
||||
|
||||
PositionReference?: PositionReference
|
||||
|
||||
/** An existing or new available container */
|
||||
AssociatedContainer?: IAvailableContainer
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ export interface ISymbolModel {
|
|||
/** Horizontal offset */
|
||||
x: number
|
||||
|
||||
// TODO: Implement Y and verticality
|
||||
|
||||
/** Width */
|
||||
width: number
|
||||
|
||||
|
|
|
@ -283,7 +283,10 @@ const GetSVGLayoutConfiguration = () => {
|
|||
Url: 'https://www.manutan.fr/img/S/GRP/ST/AIG3930272.jpg'
|
||||
},
|
||||
Name: 'Poteau structure',
|
||||
PositionReference: 1
|
||||
PositionReference: 1,
|
||||
AssociatedContainer: {
|
||||
Type: 'Montant'
|
||||
}
|
||||
},
|
||||
{
|
||||
Width: 32,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue