332 lines
10 KiB
TypeScript
332 lines
10 KiB
TypeScript
import { PositionReference } from '../Enums/PositionReference';
|
|
import { type IAvailableContainer } from '../Interfaces/IAvailableContainer';
|
|
import { type IAvailableSymbol } from '../Interfaces/IAvailableSymbol';
|
|
import { type IConfiguration } from '../Interfaces/IConfiguration';
|
|
import { ContainerModel, type IContainerModel } from '../Interfaces/IContainerModel';
|
|
import { type IContainerProperties } from '../Interfaces/IContainerProperties';
|
|
import { type IEditorState } from '../Interfaces/IEditorState';
|
|
import { type ISymbolModel } from '../Interfaces/ISymbolModel';
|
|
import { Orientation } from '../Enums/Orientation';
|
|
import { AppState } from '../Enums/AppState';
|
|
import { type IDimensionOptions } from '../Interfaces/IDimensionOptions';
|
|
import { type IDimensionStyle } from '../Interfaces/IDimensionStyle';
|
|
|
|
/// EDITOR DEFAULTS ///
|
|
|
|
/** Enable fast boot and disable main menu (0 = disabled, 1 = loading, 2 = loaded) */
|
|
export const FAST_BOOT = import.meta.env.PROD
|
|
? AppState.Loaded
|
|
: AppState.MainMenu;
|
|
|
|
/** Disable any call to the API (default = false) */
|
|
export const DISABLE_API = false;
|
|
|
|
export const DEFAULT_LANGUAGE = 'fr';
|
|
|
|
/**
|
|
* Replace the SVG viewer by a canvas
|
|
* Better compatibility with Gecko and WebKit engines like Firefox and Safari.
|
|
* EXPERIMENTAL: svg export wont work and it won't be possible to insert a custom svg)
|
|
*/
|
|
export const USE_EXPERIMENTAL_CANVAS_API = false;
|
|
|
|
/** Enable keyboard shortcuts (default = true) */
|
|
export const ENABLE_SHORTCUTS = true;
|
|
|
|
/** Size of the history (recommanded = 200) */
|
|
export const MAX_HISTORY = 200;
|
|
|
|
/** Apply beheviors on children (recommanded = true) */
|
|
export const APPLY_BEHAVIORS_ON_CHILDREN = true;
|
|
|
|
/** Framerate of the svg controller (recommanded = 60) */
|
|
export const MAX_FRAMERATE = 120;
|
|
|
|
/// CONTAINER DEFAULTS ///
|
|
|
|
/** Enable the swap behavior (kinda broken recommanded = false) */
|
|
export const ENABLE_SWAP = false;
|
|
|
|
/** Enable the rigid behavior (recommanded = true) */
|
|
export const ENABLE_RIGID = true;
|
|
|
|
/**
|
|
* Enable the hard rigid behavior
|
|
* disallowing the container to overlap (ENABLE_RIGID must be true)
|
|
* (recommanded = false)
|
|
*/
|
|
export const ENABLE_HARD_RIGID = false;
|
|
|
|
/** Enalbe the text in the containers */
|
|
export const SHOW_TEXT = false;
|
|
export const SHOW_SELECTOR_TEXT = true;
|
|
export const DEFAULTCHILDTYPE_ALLOW_CYCLIC = false;
|
|
export const DEFAULTCHILDTYPE_MAX_DEPTH = 10;
|
|
|
|
/// DIMENSIONS DEFAULTS ///
|
|
|
|
export const SHOW_SELF_DIMENSIONS = true;
|
|
export const SHOW_SELF_MARGINS_DIMENSIONS = true;
|
|
export const SHOW_CHILDREN_DIMENSIONS = true;
|
|
export const SHOW_BORROWER_DIMENSIONS = true;
|
|
export const DIMENSION_MARGIN = 70;
|
|
export const SYMBOL_DIMENSION_MARGIN = 30;
|
|
export const SYMBOL_MARGIN = 25;
|
|
export const NOTCHES_LENGTH = 10;
|
|
export const DEFAULT_DIMENSION_SYMBOL_STYLE: IDimensionStyle = {
|
|
color: '#000000'
|
|
};
|
|
|
|
/// SYMBOL DEFAULTS ///
|
|
|
|
export const DEFAULT_SYMBOL_WIDTH = 32;
|
|
export const DEFAULT_SYMBOL_IS_VERTICAL = false;
|
|
export const DEFAULT_SYMBOL_HEIGHT = 32;
|
|
|
|
/**
|
|
* Returns the default editor state given the configuration
|
|
*/
|
|
export function GetDefaultEditorState(configuration: IConfiguration): IEditorState {
|
|
if (configuration.MainContainer.Width === undefined ||
|
|
configuration.MainContainer.Height === undefined) {
|
|
throw new Error('Cannot initialize project! Main container has an undefined size');
|
|
}
|
|
|
|
const containerConfig = configuration.AvailableContainers.find(
|
|
config => config.Type === configuration.MainContainer.Type
|
|
);
|
|
|
|
let mainContainerConfig: IContainerProperties;
|
|
if (containerConfig !== undefined) {
|
|
const clone = structuredClone(containerConfig);
|
|
const extendedContainerConfig = Object.assign(clone, configuration.MainContainer);
|
|
|
|
if (containerConfig.Style !== undefined) {
|
|
const styleClone = structuredClone(containerConfig.Style);
|
|
extendedContainerConfig.Style = Object.assign(styleClone, configuration.MainContainer.Style);
|
|
}
|
|
|
|
if (extendedContainerConfig.Width === undefined ||
|
|
extendedContainerConfig.Height === undefined) {
|
|
throw new Error('Cannot initialize project! Main container has an undefined size');
|
|
}
|
|
|
|
mainContainerConfig = GetDefaultContainerProps(
|
|
extendedContainerConfig.Type,
|
|
0,
|
|
null,
|
|
0,
|
|
0,
|
|
extendedContainerConfig.Width,
|
|
extendedContainerConfig.Height,
|
|
extendedContainerConfig
|
|
);
|
|
} else {
|
|
mainContainerConfig = GetDefaultContainerProps(
|
|
configuration.MainContainer.Type,
|
|
0,
|
|
null,
|
|
0,
|
|
0,
|
|
configuration.MainContainer.Width,
|
|
configuration.MainContainer.Height,
|
|
configuration.MainContainer
|
|
);
|
|
}
|
|
const mainContainer = new ContainerModel(mainContainerConfig);
|
|
const containers = new Map<string, IContainerModel>();
|
|
containers.set(mainContainer.properties.id, mainContainer);
|
|
|
|
const typeCounters = {};
|
|
(typeCounters as any)[mainContainer.properties.type] = 0;
|
|
|
|
return {
|
|
configuration,
|
|
history: [
|
|
{
|
|
lastAction: '',
|
|
mainContainer: mainContainer.properties.id,
|
|
containers,
|
|
typeCounters,
|
|
symbols: new Map()
|
|
}
|
|
],
|
|
historyCurrentStep: 0,
|
|
version: APP_VERSION ?? 'test-version'
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Default config when the API is not available
|
|
*/
|
|
export const DEFAULT_CONFIG: IConfiguration = {
|
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
AvailableContainers: [
|
|
{
|
|
Type: 'Container',
|
|
MaxWidth: 200,
|
|
Height: 100,
|
|
Style: {
|
|
fillOpacity: 0,
|
|
stroke: 'green'
|
|
}
|
|
}
|
|
],
|
|
AvailableSymbols: [],
|
|
Categories: [],
|
|
Patterns: [],
|
|
MainContainer: {
|
|
Type: 'Container',
|
|
Width: 800,
|
|
Height: 100,
|
|
Style: {
|
|
fillOpacity: 0,
|
|
stroke: 'black'
|
|
}
|
|
}
|
|
/* eslint-enable */
|
|
};
|
|
|
|
const DEFAULT_CONTAINER_STYLE = {
|
|
stroke: 'black',
|
|
fillOpacity: 1,
|
|
fill: 'white',
|
|
strokeWidth: 2
|
|
};
|
|
|
|
export const DEFAULT_DIMENSION_OPTION: IDimensionOptions = {
|
|
positions: [],
|
|
color: '#000000',
|
|
width: 2
|
|
};
|
|
|
|
/**
|
|
* Default Main container properties
|
|
*/
|
|
export const DEFAULT_MAINCONTAINER_PROPS: IContainerProperties = {
|
|
id: 'main',
|
|
type: 'container',
|
|
parentId: '',
|
|
linkedSymbolId: '',
|
|
displayedText: 'main',
|
|
orientation: Orientation.Horizontal,
|
|
x: 0,
|
|
y: 0,
|
|
margin: {},
|
|
minWidth: 1,
|
|
maxWidth: Number.MAX_SAFE_INTEGER,
|
|
minHeight: 1,
|
|
maxHeight: Number.MAX_SAFE_INTEGER,
|
|
width: Number(DEFAULT_CONFIG.MainContainer.Width),
|
|
height: Number(DEFAULT_CONFIG.MainContainer.Height),
|
|
isAnchor: false,
|
|
isFlex: false,
|
|
positionReference: PositionReference.TopLeft,
|
|
hideChildrenInTreeview: false,
|
|
dimensionOptions: {
|
|
childrenDimensions: clone(DEFAULT_DIMENSION_OPTION),
|
|
selfDimensions: clone(DEFAULT_DIMENSION_OPTION),
|
|
selfMarginsDimensions: clone(DEFAULT_DIMENSION_OPTION),
|
|
markPosition: [],
|
|
dimensionWithMarks: clone(DEFAULT_DIMENSION_OPTION)
|
|
},
|
|
warning: '',
|
|
style: DEFAULT_CONTAINER_STYLE
|
|
};
|
|
|
|
/**
|
|
* Returns the default properties of a newly created container
|
|
* @param type Type of the container
|
|
* @param typeCount index of the container
|
|
* @param parent Parent of the container
|
|
* @param x horizontal offset
|
|
* @param y vertical offset
|
|
* @param width
|
|
* @param height
|
|
* @param containerConfig default config of the container sent by the API
|
|
* @returns {IContainerProperties} Default properties of a newly created container
|
|
*/
|
|
export function GetDefaultContainerProps(
|
|
type: string,
|
|
typeCount: number,
|
|
parent: IContainerModel | undefined | null,
|
|
x: number,
|
|
y: number,
|
|
width: number,
|
|
height: number,
|
|
containerConfig: IAvailableContainer
|
|
): IContainerProperties {
|
|
const orientation = containerConfig.Orientation ?? Orientation.Horizontal;
|
|
return ({
|
|
id: `${type}-${typeCount}`,
|
|
type,
|
|
parentId: parent?.properties.id ?? '',
|
|
linkedSymbolId: '',
|
|
displayedText: `${containerConfig.DisplayedText ?? type}-${typeCount}`,
|
|
orientation,
|
|
x,
|
|
y,
|
|
margin: containerConfig.Margin ?? {},
|
|
width,
|
|
height,
|
|
isAnchor: containerConfig.IsAnchor ?? false,
|
|
isFlex: containerConfig.IsFlex ?? false,
|
|
positionReference: containerConfig.PositionReference ?? PositionReference.TopLeft,
|
|
minWidth: containerConfig.MinWidth ?? 1,
|
|
maxWidth: containerConfig.MaxWidth ?? Number.MAX_SAFE_INTEGER,
|
|
minHeight: containerConfig.MinWidth ?? 1,
|
|
maxHeight: containerConfig.MaxWidth ?? Number.MAX_SAFE_INTEGER,
|
|
hideChildrenInTreeview: containerConfig.HideChildrenInTreeview ?? false,
|
|
dimensionOptions: {
|
|
childrenDimensions: {
|
|
...containerConfig.DimensionOptions?.childrenDimensions,
|
|
positions: containerConfig.DimensionOptions?.childrenDimensions?.positions ?? []
|
|
},
|
|
selfDimensions: {
|
|
...containerConfig.DimensionOptions?.selfDimensions,
|
|
positions: containerConfig.DimensionOptions?.selfDimensions?.positions ?? []
|
|
},
|
|
selfMarginsDimensions: {
|
|
...containerConfig.DimensionOptions?.selfMarginsDimensions,
|
|
positions: containerConfig.DimensionOptions?.selfMarginsDimensions?.positions ?? []
|
|
},
|
|
markPosition: containerConfig.DimensionOptions?.markPosition ?? [],
|
|
dimensionWithMarks: {
|
|
...containerConfig.DimensionOptions?.dimensionWithMarks,
|
|
positions: containerConfig.DimensionOptions?.dimensionWithMarks?.positions ?? []
|
|
}
|
|
},
|
|
warning: '',
|
|
customSVG: containerConfig.CustomSVG,
|
|
style: Object.assign(structuredClone(DEFAULT_CONTAINER_STYLE), structuredClone(containerConfig.Style)),
|
|
userData: structuredClone(containerConfig.UserData)
|
|
});
|
|
}
|
|
|
|
export function GetDefaultSymbolModel(
|
|
name: string,
|
|
newCounters: Record<string, number>,
|
|
type: string,
|
|
symbolConfig: IAvailableSymbol
|
|
): ISymbolModel {
|
|
const id = `${name}-${newCounters[type]}`;
|
|
return {
|
|
id,
|
|
displayedText: symbolConfig.DisplayedText ?? id,
|
|
type: name,
|
|
config: structuredClone(symbolConfig),
|
|
offset: 0,
|
|
isVertical: symbolConfig.isVertical ?? DEFAULT_SYMBOL_IS_VERTICAL,
|
|
width: symbolConfig.Width ?? DEFAULT_SYMBOL_WIDTH,
|
|
height: symbolConfig.Height ?? DEFAULT_SYMBOL_HEIGHT,
|
|
linkedContainers: new Set(),
|
|
showDimension: false
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Macro function for JSON.parse(JSON.stringify(obj))
|
|
*/
|
|
function clone<T>(object: T): T {
|
|
return JSON.parse(JSON.stringify(object));
|
|
}
|