Merged PR 311: #7975 Cotations sur les ancrages

![image.png](e30b9bba-4b18-4276-b4ef-74d97b7daef3/pullRequests/311/attachments/image.png)

Related work items: #7975
This commit is contained in:
Carl Fuchs 2023-02-07 10:16:19 +00:00 committed by Eric Nguyen
parent 532151b939
commit acb5ba2d82
7 changed files with 251 additions and 182 deletions

View file

@ -1,4 +1,4 @@
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Collections.Generic; using System.Collections.Generic;
namespace SVGLDLibs.Models namespace SVGLDLibs.Models
@ -26,5 +26,8 @@ namespace SVGLDLibs.Models
[DataMember(EmitDefaultValue = false)] [DataMember(EmitDefaultValue = false)]
public List<string> linkedContainers { get; set; } public List<string> linkedContainers { get; set; }
[DataMember(EmitDefaultValue = false)]
public List<bool> showDimension { get; set; }
} }
} }

View file

@ -5,10 +5,18 @@ import { ISymbolModel } from '../../Interfaces/ISymbolModel';
import { import {
SHOW_BORROWER_DIMENSIONS, SHOW_BORROWER_DIMENSIONS,
SHOW_CHILDREN_DIMENSIONS, SHOW_CHILDREN_DIMENSIONS,
SHOW_SELF_DIMENSIONS, SHOW_SELF_DIMENSIONS, SHOW_SELF_MARGINS_DIMENSIONS
SHOW_SELF_MARGINS_DIMENSIONS
} from '../../utils/default'; } from '../../utils/default';
import { ApplyWidthMargin, ApplyXMargin, RemoveWidthMargin, RemoveXMargin, RestoreX, RestoreY, TransformX, TransformY } from '../../utils/svg'; import {
ApplyWidthMargin,
ApplyXMargin,
RemoveWidthMargin,
RemoveXMargin,
RestoreX,
RestoreY,
TransformX,
TransformY
} from '../../utils/svg';
import { Text } from '../Text/Text'; import { Text } from '../Text/Text';
import { InputGroup } from '../InputGroup/InputGroup'; import { InputGroup } from '../InputGroup/InputGroup';
import { TextInputGroup } from '../InputGroup/TextInputGroup'; import { TextInputGroup } from '../InputGroup/TextInputGroup';
@ -38,7 +46,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='' inputClassName=''
type='string' type='string'
value={props.properties.displayedText?.toString()} value={props.properties.displayedText?.toString()}
onChange={(value) => props.onChange('displayedText', value)} /> onChange={(value) => props.onChange('displayedText', value)}/>
<OrientationSelector <OrientationSelector
id='orientation' id='orientation'
name='Orientation' name='Orientation'
@ -63,7 +71,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='' inputClassName=''
type='string' type='string'
value={props.properties.id.toString()} value={props.properties.id.toString()}
isDisabled={true} /> isDisabled={true}/>
</div> </div>
<div> <div>
<InputGroup <InputGroup
@ -73,7 +81,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='' inputClassName=''
type='string' type='string'
value={props.properties.parentId} value={props.properties.parentId}
isDisabled={true} /> isDisabled={true}/>
</div> </div>
<div> <div>
<InputGroup <InputGroup
@ -83,7 +91,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='' inputClassName=''
type='string' type='string'
value={props.properties.type} value={props.properties.type}
isDisabled={true} /> isDisabled={true}/>
</div> </div>
</div> </div>
</Category> </Category>
@ -119,7 +127,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
), ),
props.properties.margin.left props.properties.margin.left
) )
)} /> )}/>
<TextInputGroup <TextInputGroup
id={`${props.properties.id}-y`} id={`${props.properties.id}-y`}
labelText={Text({ textId: '@ContainerY' })} labelText={Text({ textId: '@ContainerY' })}
@ -142,7 +150,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
), ),
props.properties.margin.top props.properties.margin.top
) )
)} /> )}/>
</div> </div>
</Category> </Category>
@ -163,7 +171,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number' type='number'
min={1} min={1}
value={props.properties.minWidth.toString()} value={props.properties.minWidth.toString()}
onChange={(value) => props.onChange('minWidth', Number(value))} /> onChange={(value) => props.onChange('minWidth', Number(value))}/>
<TextInputGroup <TextInputGroup
id={`${props.properties.id}-width`} id={`${props.properties.id}-width`}
labelText={Text({ textId: '@ContainerWidth' })} labelText={Text({ textId: '@ContainerWidth' })}
@ -175,7 +183,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
max={props.properties.maxWidth} max={props.properties.maxWidth}
value={(RemoveWidthMargin(props.properties.width, props.properties.margin.left, props.properties.margin.right)).toString()} value={(RemoveWidthMargin(props.properties.width, props.properties.margin.left, props.properties.margin.right)).toString()}
onChange={(value) => props.onChange('width', ApplyWidthMargin(Number(value), props.properties.margin.left, props.properties.margin.right))} onChange={(value) => props.onChange('width', ApplyWidthMargin(Number(value), props.properties.margin.left, props.properties.margin.right))}
isDisabled={props.properties.isFlex} /> isDisabled={props.properties.isFlex}/>
<TextInputGroup <TextInputGroup
id={`${props.properties.id}-maxWidth`} id={`${props.properties.id}-maxWidth`}
labelText={Text({ textId: '@ContainerMaxWidth' })} labelText={Text({ textId: '@ContainerMaxWidth' })}
@ -185,7 +193,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number' type='number'
min={1} min={1}
value={props.properties.maxWidth.toString()} value={props.properties.maxWidth.toString()}
onChange={(value) => props.onChange('maxWidth', Number(value))} /> onChange={(value) => props.onChange('maxWidth', Number(value))}/>
<div className='col-span-5 p-3'></div> <div className='col-span-5 p-3'></div>
<TextInputGroup <TextInputGroup
id={`${props.properties.id}-minHeight`} id={`${props.properties.id}-minHeight`}
@ -196,7 +204,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number' type='number'
min={1} min={1}
value={props.properties.minHeight.toString()} value={props.properties.minHeight.toString()}
onChange={(value) => props.onChange('minHeight', Number(value))} /> onChange={(value) => props.onChange('minHeight', Number(value))}/>
<TextInputGroup <TextInputGroup
id={`${props.properties.id}-height`} id={`${props.properties.id}-height`}
labelText={Text({ textId: '@ContainerHeight' })} labelText={Text({ textId: '@ContainerHeight' })}
@ -219,7 +227,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number' type='number'
min={1} min={1}
value={props.properties.maxHeight.toString()} value={props.properties.maxHeight.toString()}
onChange={(value) => props.onChange('maxHeight', Number(value))} /> onChange={(value) => props.onChange('maxHeight', Number(value))}/>
</div> </div>
</Category> </Category>
@ -239,7 +247,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number' type='number'
min={0} min={0}
value={(props.properties.margin.left ?? 0).toString()} value={(props.properties.margin.left ?? 0).toString()}
onChange={(value) => props.onChange('left', Number(value), PropertyType.Margin)} /> onChange={(value) => props.onChange('left', Number(value), PropertyType.Margin)}/>
<TextInputGroup <TextInputGroup
id={`${props.properties.id}-mb`} id={`${props.properties.id}-mb`}
labelText={Text({ textId: '@ContainerMarginBottom' })} labelText={Text({ textId: '@ContainerMarginBottom' })}
@ -249,7 +257,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number' type='number'
min={0} min={0}
value={(props.properties.margin.bottom ?? 0).toString()} value={(props.properties.margin.bottom ?? 0).toString()}
onChange={(value) => props.onChange('bottom', Number(value), PropertyType.Margin)} /> onChange={(value) => props.onChange('bottom', Number(value), PropertyType.Margin)}/>
<TextInputGroup <TextInputGroup
id={`${props.properties.id}-mt`} id={`${props.properties.id}-mt`}
labelText={Text({ textId: '@ContainerMarginTop' })} labelText={Text({ textId: '@ContainerMarginTop' })}
@ -259,7 +267,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number' type='number'
min={0} min={0}
value={(props.properties.margin.top ?? 0).toString()} value={(props.properties.margin.top ?? 0).toString()}
onChange={(value) => props.onChange('top', Number(value), PropertyType.Margin)} /> onChange={(value) => props.onChange('top', Number(value), PropertyType.Margin)}/>
<TextInputGroup <TextInputGroup
id={`${props.properties.id}-mr`} id={`${props.properties.id}-mr`}
labelText={Text({ textId: '@ContainerMarginRight' })} labelText={Text({ textId: '@ContainerMarginRight' })}
@ -269,7 +277,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number' type='number'
min={0} min={0}
value={(props.properties.margin.right ?? 0).toString()} value={(props.properties.margin.right ?? 0).toString()}
onChange={(value) => props.onChange('right', Number(value), PropertyType.Margin)} /> onChange={(value) => props.onChange('right', Number(value), PropertyType.Margin)}/>
</div> </div>
</Category> </Category>
@ -296,7 +304,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='ml-auto mr-auto block' inputClassName='ml-auto mr-auto block'
type={ToggleType.Full} type={ToggleType.Full}
checked={props.properties.isAnchor} checked={props.properties.isAnchor}
onChange={(event) => props.onChange('isAnchor', event.target.checked)} /> onChange={(event) => props.onChange('isAnchor', event.target.checked)}/>
</div> </div>
</Category> </Category>
@ -326,7 +334,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
value: symbol.id value: symbol.id
}))} }))}
value={props.properties.linkedSymbolId ?? ''} value={props.properties.linkedSymbolId ?? ''}
onChange={(event) => props.onChange('linkedSymbolId', event.target.value)} /> onChange={(event) => props.onChange('linkedSymbolId', event.target.value)}/>
</div> </div>
</Category> </Category>
@ -435,7 +443,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
</div> </div>
</Category> </Category>
{ props.properties.style !== undefined && {props.properties.style !== undefined &&
<Category category={{ <Category category={{
Type: 'Style', Type: 'Style',
DisplayedText: Text({ textId: '@ContainerStyle' }) DisplayedText: Text({ textId: '@ContainerStyle' })

View file

@ -12,9 +12,11 @@ import {
import { FindContainerById, MakeRecursionDFSIterator, Pairwise } from '../../../utils/itertools'; import { FindContainerById, MakeRecursionDFSIterator, Pairwise } from '../../../utils/itertools';
import { TransformX, TransformY } from '../../../utils/svg'; import { TransformX, TransformY } from '../../../utils/svg';
import { Dimension } from './Dimension'; import { Dimension } from './Dimension';
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
interface IDimensionLayerProps { interface IDimensionLayerProps {
containers: Map<string, IContainerModel> containers: Map<string, IContainerModel>
symbols: Map<string, ISymbolModel>
root: IContainerModel root: IContainerModel
scale: number scale: number
} }
@ -35,7 +37,8 @@ function ActionByPosition(
horizontalAction: (dim: number, ...params: any[]) => void, horizontalAction: (dim: number, ...params: any[]) => void,
verticalAction: (dim: number, isRight: boolean, ...params: any[]) => void, verticalAction: (dim: number, isRight: boolean, ...params: any[]) => void,
params: any[] params: any[]
): void { ): boolean {
let incrementDepthSymbols = false;
positions.forEach((position: Position) => { positions.forEach((position: Position) => {
const dim = dimMapped[position]; const dim = dimMapped[position];
switch (position) { switch (position) {
@ -47,10 +50,12 @@ function ActionByPosition(
} }
case Position.Down: case Position.Down:
case Position.Up: case Position.Up:
incrementDepthSymbols = true;
horizontalAction(dim, ...params); horizontalAction(dim, ...params);
break; break;
} }
}); });
return incrementDepthSymbols;
} }
/** /**
@ -58,7 +63,7 @@ function ActionByPosition(
* @param param0 Object with the root container and the scale of the svg * @param param0 Object with the root container and the scale of the svg
* @returns A list of dimensions * @returns A list of dimensions
*/ */
function Dimensions({ containers, root, scale }: IDimensionLayerProps): React.ReactNode[] { function Dimensions({ containers, symbols, root, scale }: IDimensionLayerProps): React.ReactNode[] {
const it = MakeRecursionDFSIterator(root, containers, 0, [0, 0]); const it = MakeRecursionDFSIterator(root, containers, 0, [0, 0]);
const dimensions: React.ReactNode[] = []; const dimensions: React.ReactNode[] = [];
const topDim = root.properties.y; const topDim = root.properties.y;
@ -69,6 +74,7 @@ function Dimensions({ containers, root, scale }: IDimensionLayerProps): React.Re
if (!SHOW_SELF_DIMENSIONS) { if (!SHOW_SELF_DIMENSIONS) {
return []; return [];
} }
let startDepthSymbols: number = 0;
for (const { container, depth, currentTransform } of it) { for (const { container, depth, currentTransform } of it) {
const offset = (DIMENSION_MARGIN * (depth + 1)) / scale; const offset = (DIMENSION_MARGIN * (depth + 1)) / scale;
@ -78,7 +84,7 @@ function Dimensions({ containers, root, scale }: IDimensionLayerProps): React.Re
const containerRightDim = rightDim + offset; const containerRightDim = rightDim + offset;
const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim]; const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim];
if (SHOW_SELF_DIMENSIONS && container.properties.dimensionOptions.selfDimensions.positions.length > 0) { if (SHOW_SELF_DIMENSIONS && container.properties.dimensionOptions.selfDimensions.positions.length > 0) {
ActionByPosition( const incrementDepthSymbol = ActionByPosition(
dimMapped, dimMapped,
container.properties.dimensionOptions.selfDimensions.positions, container.properties.dimensionOptions.selfDimensions.positions,
AddHorizontalSelfDimension, AddHorizontalSelfDimension,
@ -90,10 +96,11 @@ function Dimensions({ containers, root, scale }: IDimensionLayerProps): React.Re
scale, scale,
container.properties.dimensionOptions.selfDimensions.color] container.properties.dimensionOptions.selfDimensions.color]
); );
if (incrementDepthSymbol) { startDepthSymbols++; }
} }
if (SHOW_SELF_MARGINS_DIMENSIONS && container.properties.dimensionOptions.selfMarginsDimensions.positions.length > 0) { if (SHOW_SELF_MARGINS_DIMENSIONS && container.properties.dimensionOptions.selfMarginsDimensions.positions.length > 0) {
ActionByPosition( const incrementDepthSymbol = ActionByPosition(
dimMapped, dimMapped,
container.properties.dimensionOptions.selfMarginsDimensions.positions, container.properties.dimensionOptions.selfMarginsDimensions.positions,
AddHorizontalSelfMarginsDimension, AddHorizontalSelfMarginsDimension,
@ -105,12 +112,14 @@ function Dimensions({ containers, root, scale }: IDimensionLayerProps): React.Re
scale, scale,
container.properties.dimensionOptions.selfMarginsDimensions.color] container.properties.dimensionOptions.selfMarginsDimensions.color]
); );
if (incrementDepthSymbol) { startDepthSymbols++; }
} }
if (SHOW_BORROWER_DIMENSIONS && container.properties.dimensionOptions.dimensionWithMarks.positions.length > 0) { if (SHOW_BORROWER_DIMENSIONS && container.properties.dimensionOptions.dimensionWithMarks.positions.length > 0) {
ActionByPosition( const incrementDepthSymbol = ActionByPosition(
dimMapped, dimMapped,
container.properties.dimensionOptions.dimensionWithMarks.positions, container.properties.dimensionOptions.dimensionWithMarks.positions,
AddHorizontalBorrowerDimension, AddHorizontalBorrowerDimension,
AddVerticalBorrowerDimension, AddVerticalBorrowerDimension,
[ [
@ -122,10 +131,11 @@ function Dimensions({ containers, root, scale }: IDimensionLayerProps): React.Re
scale, scale,
container.properties.dimensionOptions.dimensionWithMarks.color] container.properties.dimensionOptions.dimensionWithMarks.color]
); );
if (incrementDepthSymbol) { startDepthSymbols++; }
} }
if (SHOW_CHILDREN_DIMENSIONS && container.properties.dimensionOptions.childrenDimensions.positions.length > 0 && container.children.length >= 2) { if (SHOW_CHILDREN_DIMENSIONS && container.properties.dimensionOptions.childrenDimensions.positions.length > 0 && container.children.length >= 2) {
ActionByPosition( const incrementDepthSymbol = ActionByPosition(
dimMapped, dimMapped,
container.properties.dimensionOptions.childrenDimensions.positions, container.properties.dimensionOptions.childrenDimensions.positions,
AddHorizontalChildrenDimension, AddHorizontalChildrenDimension,
@ -138,12 +148,50 @@ function Dimensions({ containers, root, scale }: IDimensionLayerProps): React.Re
scale, scale,
container.properties.dimensionOptions.childrenDimensions.color] container.properties.dimensionOptions.childrenDimensions.color]
); );
if (incrementDepthSymbol) { startDepthSymbols++; }
}
}
for (const symbol of symbols) {
if (symbol[1].showDimension) {
startDepthSymbols++;
AddHorizontalSymbolDimension(symbol[1], dimensions, scale, 'black', startDepthSymbols);
} }
} }
return dimensions; return dimensions;
} }
function AddHorizontalSymbolDimension(symbol: ISymbolModel,
dimensions: React.ReactNode[],
scale: number,
color: string,
depth: number
): void {
const width = symbol.x + (symbol.width / 2);
if (width != null && width > 0) {
const id = `dim-y-margin-left${symbol.width.toFixed(0)}-${symbol.id}`;
const offset = (DIMENSION_MARGIN * (depth + 1)) / scale;
const text = width
.toFixed(0)
.toString();
dimensions.push(
<Dimension
key={id}
id={id}
xStart={0}
yStart={-offset}
xEnd={width}
yEnd={-offset}
text={text}
scale={scale}
color={color}/>
);
}
}
/** /**
* A layer containing all dimension * A layer containing all dimension
* @param props * @param props
@ -152,7 +200,7 @@ function Dimensions({ containers, root, scale }: IDimensionLayerProps): React.Re
export function DimensionLayer(props: IDimensionLayerProps): JSX.Element { export function DimensionLayer(props: IDimensionLayerProps): JSX.Element {
return ( return (
<g> <g>
{ Dimensions(props) } {Dimensions(props)}
</g> </g>
); );
} }
@ -230,7 +278,6 @@ function AddVerticalChildrenDimension(
dimensions: React.ReactNode[], dimensions: React.ReactNode[],
scale: number, scale: number,
color: string color: string
): void { ): void {
const childrenId = `dim-x${xDim.toFixed(0)}-children-${container.properties.id}`; const childrenId = `dim-x${xDim.toFixed(0)}-children-${container.properties.id}`;
@ -451,7 +498,6 @@ function AddVerticalSelfDimension(
} }
function AddHorizontalSelfDimension( function AddHorizontalSelfDimension(
yDim: number, yDim: number,
container: IContainerModel, container: IContainerModel,
currentTransform: [number, number], currentTransform: [number, number],
@ -481,7 +527,6 @@ function AddHorizontalSelfDimension(
} }
function AddHorizontalSelfMarginsDimension( function AddHorizontalSelfMarginsDimension(
yDim: number, yDim: number,
container: IContainerModel, container: IContainerModel,
currentTransform: [number, number], currentTransform: [number, number],

View file

@ -97,7 +97,7 @@ export function SVG(props: ISVGProps): JSX.Element {
{SHOW_DIMENSIONS_PER_DEPTH {SHOW_DIMENSIONS_PER_DEPTH
? <DepthDimensionLayer containers={props.containers} scale={scale} roots={props.children} /> ? <DepthDimensionLayer containers={props.containers} scale={scale} roots={props.children} />
: null} : null}
<DimensionLayer containers={props.containers} scale={scale} root={props.children} /> <DimensionLayer containers={props.containers} symbols={props.symbols} scale={scale} root={props.children} />
<SymbolLayer scale={scale} symbols={props.symbols} /> <SymbolLayer scale={scale} symbols={props.symbols} />
<Selector containers={props.containers} scale={scale} selected={props.selected} /> {/* leave this at the end so it can be removed during the svg export */} <Selector containers={props.containers} scale={scale} selected={props.selected} /> {/* leave this at the end so it can be removed during the svg export */}
</svg> </svg>

View file

@ -4,6 +4,8 @@ import { RestoreX, TransformX } from '../../utils/svg';
import { InputGroup } from '../InputGroup/InputGroup'; import { InputGroup } from '../InputGroup/InputGroup';
import { TextInputGroup } from '../InputGroup/TextInputGroup'; import { TextInputGroup } from '../InputGroup/TextInputGroup';
import { Text } from '../Text/Text'; import { Text } from '../Text/Text';
import { PropertyType } from '../../Enums/PropertyType';
import { ToggleButton } from '../ToggleButton/ToggleButton';
interface ISymbolFormProps { interface ISymbolFormProps {
symbol: ISymbolModel symbol: ISymbolModel
@ -60,6 +62,13 @@ export function SymbolForm(props: ISymbolFormProps): JSX.Element {
min={0} min={0}
value={props.symbol.width.toString()} value={props.symbol.width.toString()}
onChange={(value) => props.onChange('width', Number(value))} /> onChange={(value) => props.onChange('width', Number(value))} />
<ToggleButton
labelText={Text({ textId: '@ShowDimension' })}
inputKey='showDimension'
labelClassName=''
inputClassName=''
checked={props.symbol.showDimension}
onChange={(e) => props.onChange('showDimension', e.target.checked)}/>
</div> </div>
); );
} }

View file

@ -26,4 +26,7 @@ export interface ISymbolModel {
/** List of linked container id */ /** List of linked container id */
linkedContainers: Set<string> linkedContainers: Set<string>
/** Dimensions options */
showDimension: boolean
} }

View file

@ -313,6 +313,7 @@ export function GetDefaultSymbolModel(name: string,
x: 0, x: 0,
width: symbolConfig.Width ?? DEFAULT_SYMBOL_WIDTH, width: symbolConfig.Width ?? DEFAULT_SYMBOL_WIDTH,
height: symbolConfig.Height ?? DEFAULT_SYMBOL_HEIGHT, height: symbolConfig.Height ?? DEFAULT_SYMBOL_HEIGHT,
linkedContainers: new Set() linkedContainers: new Set(),
showDimension: false
}; };
} }