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(); 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, 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(object: T): T { return JSON.parse(JSON.stringify(object)); }