Merge branch 'master' into master.7373.symbolHighlight

This commit is contained in:
Eric NGUYEN 2023-02-13 16:22:06 +01:00
commit 6958513dd3
18 changed files with 487 additions and 464 deletions

View file

@ -18,11 +18,6 @@ namespace SVGLDLibs.Models
/** color */
[DataMember(EmitDefaultValue = false)]
public string color;
public DimensionStyle style;
}
}

View file

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
namespace SVGLDLibs.Models
{
[DataContract]
public class DimensionStyle
{
/** color */
[DataMember(EmitDefaultValue = false)]
public string color;
/** width */
[DataMember(EmitDefaultValue = false)]
public double width;
/** color */
[DataMember(EmitDefaultValue = false)]
public string dashArray;
}
}

View file

@ -10,7 +10,7 @@ import { IConfiguration } from '../../Interfaces/IConfiguration';
import { IContainerModel, ContainerModel } from '../../Interfaces/IContainerModel';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { IPattern } from '../../Interfaces/IPattern';
import { DEFAULT_MAINCONTAINER_PROPS, GetDefaultContainerProps } from '../../utils/default';
import { DEFAULT_DIMENSION_OPTION, DEFAULT_MAINCONTAINER_PROPS, GetDefaultContainerProps } from '../../utils/default';
import { FetchConfiguration } from './api';
const CSHARP_WEB_API_BASE_URL = 'http://localhost:5209/';
@ -144,23 +144,11 @@ describe.concurrent('Models test suite', () => {
PositionReference: 0,
HideChildrenInTreeview: true,
DimensionOptions: {
childrenDimensions: {
color: '#000000',
positions: []
},
selfDimensions: {
color: '#000000',
positions: []
},
selfMarginsDimensions: {
color: '#000000',
positions: []
},
childrenDimensions: DEFAULT_DIMENSION_OPTION,
selfDimensions: DEFAULT_DIMENSION_OPTION,
selfMarginsDimensions: DEFAULT_DIMENSION_OPTION,
markPosition: [],
dimensionWithMarks: {
color: '#000000',
positions: []
}
dimensionWithMarks: DEFAULT_DIMENSION_OPTION
},
IsHidden: true,
Blacklist: [

View file

@ -1,7 +1,7 @@
import * as React from 'react';
import { PropertyType } from '../../Enums/PropertyType';
import { IContainerProperties } from '../../Interfaces/IContainerProperties';
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
import { type IContainerProperties } from '../../Interfaces/IContainerProperties';
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
import {
SHOW_BORROWER_DIMENSIONS,
SHOW_CHILDREN_DIMENSIONS,
@ -46,7 +46,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName=''
type='string'
value={props.properties.displayedText?.toString()}
onChange={(value) => props.onChange('displayedText', value)}/>
onChange={(value) => { props.onChange('displayedText', value); }}/>
<OrientationSelector
id='orientation'
name='Orientation'
@ -117,7 +117,8 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
props.properties.width,
props.properties.positionReference
).toString()}
onChange={(value) => props.onChange(
onChange={(value) => {
props.onChange(
'x',
ApplyXMargin(
RestoreX(
@ -127,7 +128,8 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
),
props.properties.margin.left
)
)}/>
);
}}/>
<TextInputGroup
id={`${props.properties.id}-y`}
labelText={Text({ textId: '@ContainerY' })}
@ -140,7 +142,8 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
props.properties.height,
props.properties.positionReference
).toString()}
onChange={(value) => props.onChange(
onChange={(value) => {
props.onChange(
'y',
ApplyXMargin(
RestoreY(
@ -150,7 +153,8 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
),
props.properties.margin.top
)
)}/>
);
}}/>
</div>
</Category>
@ -171,7 +175,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={1}
value={props.properties.minWidth.toString()}
onChange={(value) => props.onChange('minWidth', Number(value))}/>
onChange={(value) => { props.onChange('minWidth', Number(value)); }}/>
<TextInputGroup
id={`${props.properties.id}-width`}
labelText={Text({ textId: '@ContainerWidth' })}
@ -182,7 +186,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
min={props.properties.minWidth}
max={props.properties.maxWidth}
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}/>
<TextInputGroup
id={`${props.properties.id}-maxWidth`}
@ -193,7 +197,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={1}
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>
<TextInputGroup
id={`${props.properties.id}-minHeight`}
@ -204,7 +208,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={1}
value={props.properties.minHeight.toString()}
onChange={(value) => props.onChange('minHeight', Number(value))}/>
onChange={(value) => { props.onChange('minHeight', Number(value)); }}/>
<TextInputGroup
id={`${props.properties.id}-height`}
labelText={Text({ textId: '@ContainerHeight' })}
@ -215,7 +219,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
min={props.properties.minHeight}
max={props.properties.maxHeight}
value={(RemoveWidthMargin(props.properties.height, props.properties.margin.top, props.properties.margin.bottom)).toString()}
onChange={(value) => props.onChange('height', ApplyWidthMargin(Number(value), props.properties.margin.top, props.properties.margin.bottom))}
onChange={(value) => { props.onChange('height', ApplyWidthMargin(Number(value), props.properties.margin.top, props.properties.margin.bottom)); }}
isDisabled={props.properties.isFlex}
/>
<TextInputGroup
@ -227,7 +231,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={1}
value={props.properties.maxHeight.toString()}
onChange={(value) => props.onChange('maxHeight', Number(value))}/>
onChange={(value) => { props.onChange('maxHeight', Number(value)); }}/>
</div>
</Category>
@ -247,7 +251,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
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
id={`${props.properties.id}-mb`}
labelText={Text({ textId: '@ContainerMarginBottom' })}
@ -257,7 +261,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
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
id={`${props.properties.id}-mt`}
labelText={Text({ textId: '@ContainerMarginTop' })}
@ -267,7 +271,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
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
id={`${props.properties.id}-mr`}
labelText={Text({ textId: '@ContainerMarginRight' })}
@ -277,7 +281,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
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>
</Category>
@ -295,7 +299,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='ml-auto mr-auto block'
type={ToggleType.Full}
checked={props.properties.isFlex}
onChange={(event) => props.onChange('isFlex', event.target.checked)}
onChange={(event) => { props.onChange('isFlex', event.target.checked); }}
/>
<ToggleButton
labelText={Text({ textId: '@ContainerAnchor' })}
@ -304,7 +308,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='ml-auto mr-auto block'
type={ToggleType.Full}
checked={props.properties.isAnchor}
onChange={(event) => props.onChange('isAnchor', event.target.checked)}/>
onChange={(event) => { props.onChange('isAnchor', event.target.checked); }}/>
</div>
</Category>
@ -334,7 +338,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
value: symbol.id
}))}
value={props.properties.linkedSymbolId ?? ''}
onChange={(event) => props.onChange('linkedSymbolId', event.target.value)}/>
onChange={(event) => { props.onChange('linkedSymbolId', event.target.value); }}/>
</div>
</Category>
@ -354,16 +358,35 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
name='ShowSelfDimensions'
labelText={Text({ textId: '@ContainerShowDimension' })}
value={props.properties.dimensionOptions.selfDimensions.positions}
onChange={(key, value) => props.onChange(key, value, PropertyType.SelfDimension)}
onChange={(key, value) => { props.onChange(key, value, PropertyType.SelfDimension); }}
/>
<InputGroup
labelText={Text({ textId: '@Color' })}
labelText={Text({ textId: '@StyleStrokeColor' })}
inputKey='color'
labelClassName=''
inputClassName=''
type='color'
value={props.properties.dimensionOptions.selfDimensions.color}
onChange={(e) => props.onChange('color', e.target.value, PropertyType.SelfDimension)}/>
value={props.properties.dimensionOptions.selfDimensions.style.color}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.SelfDimensionStyle); }}/>
<TextInputGroup
id={`${props.properties.id}-selfDimensions-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
inputKey='width'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.dimensionOptions.selfDimensions.style.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.SelfDimensionStyle); }}/>
<TextInputGroup
id={`${props.properties.id}-selfDimensions-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
inputKey='dashArray'
labelClassName=''
inputClassName=''
type='text'
value={props.properties.dimensionOptions.selfDimensions.style.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.SelfDimensionStyle); }}/>
</div>
}
{
@ -375,16 +398,35 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
name='ShowSelfMarginsDimensions'
labelText={Text({ textId: '@ContainerShowMarginsDimension' })}
value={props.properties.dimensionOptions.selfMarginsDimensions.positions}
onChange={(key, value) => props.onChange(key, value, PropertyType.SelfMarginDimension)}
onChange={(key, value) => { props.onChange(key, value, PropertyType.SelfMarginDimension); }}
/>
<InputGroup
labelText={Text({ textId: '@Color' })}
labelText={Text({ textId: '@StyleStrokeColor' })}
inputKey='color'
labelClassName=''
inputClassName=''
type='color'
value={props.properties.dimensionOptions.selfMarginsDimensions.color}
onChange={(e) => props.onChange('color', e.target.value, PropertyType.SelfMarginDimension)}/>
value={props.properties.dimensionOptions.selfMarginsDimensions.style.color}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.SelfMarginDimensionStyle); }}/>
<TextInputGroup
id={`${props.properties.id}-selfMarginsDimensions-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
inputKey='width'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.dimensionOptions.selfMarginsDimensions.style.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.SelfMarginDimensionStyle); }}/>
<TextInputGroup
id={`${props.properties.id}-selfMarginsDimensions-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
inputKey='dashArray'
labelClassName=''
inputClassName=''
type='text'
value={props.properties.dimensionOptions.selfMarginsDimensions.style.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.SelfMarginDimensionStyle); }}/>
</div>
}
{
@ -396,16 +438,35 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
name='ShowChildrenDimensions'
labelText={Text({ textId: '@ContainerShowChildrenDimension' })}
value={props.properties.dimensionOptions.childrenDimensions.positions}
onChange={(key, value) => props.onChange(key, value, PropertyType.ChildrenDimensions)}
onChange={(key, value) => { props.onChange(key, value, PropertyType.ChildrenDimensions); }}
/>
<InputGroup
labelText={Text({ textId: '@Color' })}
labelText={Text({ textId: '@StyleStrokeColor' })}
inputKey='color'
labelClassName=''
inputClassName=''
type='color'
value={props.properties.dimensionOptions.childrenDimensions.color}
onChange={(e) => props.onChange('color', e.target.value, PropertyType.ChildrenDimensions)}/>
value={props.properties.dimensionOptions.childrenDimensions.style.color}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.ChildrenDimensionsStyle); }}/>
<TextInputGroup
id={`${props.properties.id}-childrenDimensions-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
inputKey='width'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.dimensionOptions.childrenDimensions.style.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.ChildrenDimensionsStyle); }}/>
<TextInputGroup
id={`${props.properties.id}-childrenDimensions-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
inputKey='dashArray'
labelClassName=''
inputClassName=''
type='text'
value={props.properties.dimensionOptions.childrenDimensions.style.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.ChildrenDimensionsStyle); }}/>
</div>
}
{
@ -417,7 +478,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
name='MarkPosition'
value={props.properties.dimensionOptions.markPosition}
labelText={Text({ textId: '@ContainerMarkPosition' })}
onChange={(key, value) => props.onChange(key, value, PropertyType.DimensionOptions)}
onChange={(key, value) => { props.onChange(key, value, PropertyType.DimensionOptions); }}
/>
</div>
<div className='grid grid-cols-1 gap-2'>
@ -427,16 +488,35 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
name='ShowDimensionWithMarks'
labelText={Text({ textId: '@ContainerShowDimensionWithMarks' })}
value={props.properties.dimensionOptions.dimensionWithMarks.positions}
onChange={(key, value) => props.onChange(key, value, PropertyType.DimensionWithMarks)}
onChange={(key, value) => { props.onChange(key, value, PropertyType.DimensionWithMarks); }}
/>
<InputGroup
labelText={Text({ textId: '@Color' })}
labelText={Text({ textId: '@StyleStrokeColor' })}
inputKey='color'
labelClassName=''
inputClassName=''
type='color'
value={props.properties.dimensionOptions.dimensionWithMarks.color}
onChange={(e) => props.onChange('color', e.target.value, PropertyType.DimensionWithMarks)}/>
value={props.properties.dimensionOptions.dimensionWithMarks.style.color}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.DimensionWithMarksStyle); }}/>
<TextInputGroup
id={`${props.properties.id}-dimensionWithMarks-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
inputKey='width'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.dimensionOptions.dimensionWithMarks.style.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.DimensionWithMarksStyle); }}/>
<TextInputGroup
id={`${props.properties.id}-dimensionWithMarks-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
inputKey='dashArray'
labelClassName=''
inputClassName=''
type='text'
value={props.properties.dimensionOptions.dimensionWithMarks.style.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.DimensionWithMarksStyle); }}/>
</div>
</>
}
@ -459,7 +539,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='col-span-3'
type='string'
value={props.properties.style.stroke ?? 'black'}
onChange={(value) => props.onChange('stroke', value, PropertyType.Style)}
onChange={(value) => { props.onChange('stroke', value, PropertyType.Style); }}
/>
<InputGroup
labelKey={`${props.properties.id}-strokeOpacity`}
@ -472,7 +552,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
max={1}
step={0.01}
value={(props.properties.style.strokeOpacity ?? 1).toString()}
onChange={(event) => props.onChange('strokeOpacity', Number(event.target.value), PropertyType.Style)}
onChange={(event) => { props.onChange('strokeOpacity', Number(event.target.value), PropertyType.Style); }}
/>
<TextInputGroup
id={`${props.properties.id}-strokeWidth`}
@ -482,7 +562,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='col-span-3'
type='number'
value={(props.properties.style.strokeWidth ?? 1).toString()}
onChange={(value) => props.onChange('strokeWidth', Number(value), PropertyType.Style)}
onChange={(value) => { props.onChange('strokeWidth', Number(value), PropertyType.Style); }}
/>
<TextInputGroup
id={`${props.properties.id}-fill`}
@ -492,7 +572,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='col-span-3'
type='string'
value={props.properties.style.fill ?? 'black'}
onChange={(value) => props.onChange('fill', value, PropertyType.Style)}
onChange={(value) => { props.onChange('fill', value, PropertyType.Style); }}
/>
<InputGroup
labelKey={`${props.properties.id}-fillOpacity`}
@ -505,7 +585,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
max={1}
step={0.01}
value={(props.properties.style.fillOpacity ?? 1).toString()}
onChange={(event) => props.onChange('fillOpacity', Number(event.target.value), PropertyType.Style)}
onChange={(event) => { props.onChange('fillOpacity', Number(event.target.value), PropertyType.Style); }}
/>
</div>
</Category>

View file

@ -5,6 +5,7 @@ import { PositionReference } from '../../Enums/PositionReference';
import { IContainerProperties } from '../../Interfaces/IContainerProperties';
import { Orientation } from '../../Enums/Orientation';
import { ContainerProperties } from './ContainerProperties';
import { DEFAULT_DIMENSION_OPTION } from '../../utils/default';
describe.concurrent('Properties', () => {
it('No properties', () => {
@ -43,23 +44,11 @@ describe.concurrent('Properties', () => {
warning: '',
hideChildrenInTreeview: false,
dimensionOptions: {
childrenDimensions: {
color: '#000000',
positions: []
},
selfDimensions: {
color: '#000000',
positions: []
},
selfMarginsDimensions: {
color: '#000000',
positions: []
},
childrenDimensions: DEFAULT_DIMENSION_OPTION,
selfDimensions: DEFAULT_DIMENSION_OPTION,
selfMarginsDimensions: DEFAULT_DIMENSION_OPTION,
markPosition: [],
dimensionWithMarks: {
color: '#000000',
positions: []
}
dimensionWithMarks: DEFAULT_DIMENSION_OPTION
}
};

View file

@ -362,6 +362,18 @@ function AssignProperty(container: IContainerModel, key: string, value: string |
case PropertyType.DimensionWithMarks:
(container.properties.dimensionOptions.dimensionWithMarks as any)[key] = value;
break;
case PropertyType.SelfDimensionStyle:
(container.properties.dimensionOptions.selfDimensions.style as any)[key] = value;
break;
case PropertyType.SelfMarginDimensionStyle:
(container.properties.dimensionOptions.selfMarginsDimensions.style as any)[key] = value;
break;
case PropertyType.ChildrenDimensionsStyle:
(container.properties.dimensionOptions.childrenDimensions.style as any)[key] = value;
break;
case PropertyType.DimensionWithMarksStyle:
(container.properties.dimensionOptions.dimensionWithMarks.style as any)[key] = value;
break;
case PropertyType.DimensionOptions:
(container.properties.dimensionOptions as any)[key] = value;
break;

View file

@ -1,100 +0,0 @@
import * as React from 'react';
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { DIMENSION_MARGIN } from '../../../utils/default';
import { GetAbsolutePosition, MakeBFSIterator } from '../../../utils/itertools';
import { TransformX } from '../../../utils/svg';
import { Dimension } from './Dimension';
interface IDimensionLayerProps {
containers: Map<string, IContainerModel>
roots: IContainerModel | IContainerModel[] | null
scale?: number
}
function GetDimensionsNodes(
containers: Map<string, IContainerModel>,
root: IContainerModel,
scale: number
): React.ReactNode[] {
const it = MakeBFSIterator(root, containers);
const dimensions: React.ReactNode[] = [];
let currentDepth = 0;
let min = Infinity;
let max = -Infinity;
let lastY = 0;
for (const { container, depth } of it) {
if (currentDepth !== depth) {
AddNewDimension(currentDepth, min, max, lastY, scale, '#000000', dimensions);
currentDepth = depth;
min = Infinity;
max = -Infinity;
}
const absoluteX = GetAbsolutePosition(containers, container)[0];
const x = TransformX(absoluteX, container.properties.width, container.properties.positionReference);
lastY = container.properties.y + container.properties.height;
if (x < min) {
min = x;
}
if (x > max) {
max = x;
}
}
AddNewDimension(currentDepth, min, max, lastY, scale, '#000000', dimensions);
return dimensions;
}
/**
* A layer containing all dimension
* @param props
* @returns
*/
export function DepthDimensionLayer(props: IDimensionLayerProps): JSX.Element {
let dimensions: React.ReactNode[] = [];
const scale = props.scale ?? 1;
if (Array.isArray(props.roots)) {
props.roots.forEach(child => {
dimensions.concat(GetDimensionsNodes(props.containers, child, scale));
});
} else if (props.roots !== null) {
dimensions = GetDimensionsNodes(props.containers, props.roots, scale);
}
return (
<g>
{dimensions}
</g>
);
}
function AddNewDimension(currentDepth: number, min: number, max: number, lastY: number, scale: number, color: string, dimensions: React.ReactNode[]): void {
const id = `dim-depth-${currentDepth}`;
const xStart = min;
const xEnd = max;
const y = lastY + (DIMENSION_MARGIN * (currentDepth + 1)) / scale;
const width = xEnd - xStart;
const text = width
.toFixed(0)
.toString();
if (width === 0) {
return;
}
dimensions.push(
<Dimension
key={id}
id={id}
xStart={xStart}
yStart={y}
xEnd={xEnd}
yEnd={y}
text={text}
scale={scale}
color={color}
/>
);
}

View file

@ -1,4 +1,5 @@
import * as React from 'react';
import { type IDimensionStyle } from '../../../Interfaces/IDimensionStyle';
import { NOTCHES_LENGTH } from '../../../utils/default';
interface IDimensionProps {
@ -8,7 +9,7 @@ interface IDimensionProps {
xEnd: number
yEnd: number
text: string
color: string
style: IDimensionStyle
scale?: number
}
@ -28,8 +29,9 @@ function ApplyParametric(x0: number, t: number, vx: number): number {
export function Dimension(props: IDimensionProps): JSX.Element {
const scale = props.scale ?? 1;
const style: React.CSSProperties = {
stroke: props.color,
strokeWidth: 2 / scale
stroke: props.style.color,
strokeWidth: (props.style.width ?? 2) / scale,
strokeDasharray: props.style.dashArray
};
/// We need to find the points of the notches
@ -79,9 +81,11 @@ export function Dimension(props: IDimensionProps): JSX.Element {
x2={endBottomX}
y2={endBottomY}
style={style}/>
<text textAnchor={'middle'} alignmentBaseline={'central'}
<text
x={textX}
y={textY}
textAnchor={'middle'}
alignmentBaseline={'central'}
style={{
transform: `rotate(${rotation}turn) scale(${1 / scale})`,
transformOrigin: `${textX}px ${textY}px`

View file

@ -1,7 +1,6 @@
import * as React from 'react';
import { Orientation } from '../../../Enums/Orientation';
import { Position } from '../../../Enums/Position';
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import {
DIMENSION_MARGIN,
SHOW_BORROWER_DIMENSIONS,
@ -12,7 +11,9 @@ import {
import { FindContainerById, MakeRecursionDFSIterator, Pairwise } from '../../../utils/itertools';
import { TransformX, TransformY } from '../../../utils/svg';
import { Dimension } from './Dimension';
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { type IDimensionStyle } from '../../../Interfaces/IDimensionStyle';
interface IDimensionLayerProps {
containers: Map<string, IContainerModel>
@ -37,8 +38,7 @@ function ActionByPosition(
horizontalAction: (dim: number, ...params: any[]) => void,
verticalAction: (dim: number, isRight: boolean, ...params: any[]) => void,
params: any[]
): boolean {
let incrementDepthSymbols = false;
): void {
positions.forEach((position: Position) => {
const dim = dimMapped[position];
switch (position) {
@ -50,12 +50,10 @@ function ActionByPosition(
}
case Position.Down:
case Position.Up:
incrementDepthSymbols = true;
horizontalAction(dim, ...params);
break;
}
});
return incrementDepthSymbols;
}
/**
@ -74,7 +72,6 @@ function Dimensions({ containers, symbols, root, scale }: IDimensionLayerProps):
if (!SHOW_SELF_DIMENSIONS) {
return [];
}
let startDepthSymbols: number = 0;
for (const { container, depth, currentTransform } of it) {
const offset = (DIMENSION_MARGIN * (depth + 1)) / scale;
@ -84,7 +81,7 @@ function Dimensions({ containers, symbols, root, scale }: IDimensionLayerProps):
const containerRightDim = rightDim + offset;
const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim];
if (SHOW_SELF_DIMENSIONS && container.properties.dimensionOptions.selfDimensions.positions.length > 0) {
const incrementDepthSymbol = ActionByPosition(
ActionByPosition(
dimMapped,
container.properties.dimensionOptions.selfDimensions.positions,
AddHorizontalSelfDimension,
@ -93,14 +90,13 @@ function Dimensions({ containers, symbols, root, scale }: IDimensionLayerProps):
container,
currentTransform,
dimensions,
scale,
container.properties.dimensionOptions.selfDimensions.color]
scale
]
);
if (incrementDepthSymbol) { startDepthSymbols++; }
}
if (SHOW_SELF_MARGINS_DIMENSIONS && container.properties.dimensionOptions.selfMarginsDimensions.positions.length > 0) {
const incrementDepthSymbol = ActionByPosition(
ActionByPosition(
dimMapped,
container.properties.dimensionOptions.selfMarginsDimensions.positions,
AddHorizontalSelfMarginsDimension,
@ -109,14 +105,13 @@ function Dimensions({ containers, symbols, root, scale }: IDimensionLayerProps):
container,
currentTransform,
dimensions,
scale,
container.properties.dimensionOptions.selfMarginsDimensions.color]
scale
]
);
if (incrementDepthSymbol) { startDepthSymbols++; }
}
if (SHOW_BORROWER_DIMENSIONS && container.properties.dimensionOptions.dimensionWithMarks.positions.length > 0) {
const incrementDepthSymbol = ActionByPosition(
ActionByPosition(
dimMapped,
container.properties.dimensionOptions.dimensionWithMarks.positions,
@ -128,14 +123,13 @@ function Dimensions({ containers, symbols, root, scale }: IDimensionLayerProps):
depth,
currentTransform,
dimensions,
scale,
container.properties.dimensionOptions.dimensionWithMarks.color]
scale
]
);
if (incrementDepthSymbol) { startDepthSymbols++; }
}
if (SHOW_CHILDREN_DIMENSIONS && container.properties.dimensionOptions.childrenDimensions.positions.length > 0 && container.children.length >= 2) {
const incrementDepthSymbol = ActionByPosition(
ActionByPosition(
dimMapped,
container.properties.dimensionOptions.childrenDimensions.positions,
AddHorizontalChildrenDimension,
@ -145,28 +139,32 @@ function Dimensions({ containers, symbols, root, scale }: IDimensionLayerProps):
container,
currentTransform,
dimensions,
scale,
container.properties.dimensionOptions.childrenDimensions.color]
scale
]
);
if (incrementDepthSymbol) { startDepthSymbols++; }
}
}
let startDepthSymbols: number = 0;
for (const symbol of symbols) {
if (symbol[1].showDimension) {
startDepthSymbols++;
AddHorizontalSymbolDimension(symbol[1], dimensions, scale, 'black', startDepthSymbols);
AddHorizontalSymbolDimension(
symbol[1],
dimensions,
scale,
startDepthSymbols
);
}
}
return dimensions;
}
function AddHorizontalSymbolDimension(symbol: ISymbolModel,
function AddHorizontalSymbolDimension(
symbol: ISymbolModel,
dimensions: React.ReactNode[],
scale: number,
color: string,
depth: number
): void {
const width = symbol.x + (symbol.width / 2);
@ -177,6 +175,11 @@ function AddHorizontalSymbolDimension(symbol: ISymbolModel,
const text = width
.toFixed(0)
.toString();
// TODO: Put this in default.ts
const defaultDimensionSymbolStyle: IDimensionStyle = {
color: 'black'
};
dimensions.push(
<Dimension
key={id}
@ -187,7 +190,7 @@ function AddHorizontalSymbolDimension(symbol: ISymbolModel,
yEnd={-offset}
text={text}
scale={scale}
color={color}/>
style={defaultDimensionSymbolStyle}/>
);
}
}
@ -213,10 +216,10 @@ function AddHorizontalChildrenDimension(
container: IContainerModel,
currentTransform: [number, number],
dimensions: React.ReactNode[],
scale: number,
color: string
scale: number
): void {
const childrenId = `dim-y${yDim.toFixed(0)}-children-${container.properties.id}`;
const style = container.properties.dimensionOptions.childrenDimensions.style;
const lastChildId = container.children[container.children.length - 1];
const lastChild = FindContainerById(containers, lastChildId);
@ -266,7 +269,7 @@ function AddHorizontalChildrenDimension(
yEnd={yDim}
text={textChildren}
scale={scale}
color={color}/>);
style={style}/>);
}
function AddVerticalChildrenDimension(
@ -276,10 +279,10 @@ function AddVerticalChildrenDimension(
container: IContainerModel,
currentTransform: [number, number],
dimensions: React.ReactNode[],
scale: number,
color: string
scale: number
): void {
const childrenId = `dim-x${xDim.toFixed(0)}-children-${container.properties.id}`;
const style = container.properties.dimensionOptions.childrenDimensions.style;
const lastChildId = container.children[container.children.length - 1];
const lastChild = FindContainerById(containers, lastChildId);
@ -334,7 +337,7 @@ function AddVerticalChildrenDimension(
yEnd={yChildrenEnd + offset}
text={textChildren}
scale={scale}
color={color}
style={style}
/>);
}
@ -345,9 +348,9 @@ function AddHorizontalBorrowerDimension(
depth: number,
currentTransform: [number, number],
dimensions: React.ReactNode[],
scale: number,
color: string
scale: number
): void {
const style = container.properties.dimensionOptions.dimensionWithMarks.style;
const it = MakeRecursionDFSIterator(container, containers, depth, currentTransform);
const marks = []; // list of vertical lines for the dimension
for (const {
@ -392,7 +395,7 @@ function AddHorizontalBorrowerDimension(
yEnd={yDim}
text={value.toFixed(0)}
scale={scale}
color={color}/>);
style={style}/>);
count++;
}
}
@ -405,9 +408,9 @@ function AddVerticalBorrowerDimension(
depth: number,
currentTransform: [number, number],
dimensions: React.ReactNode[],
scale: number,
color: string
scale: number
): void {
const style = container.properties.dimensionOptions.dimensionWithMarks.style;
const it = MakeRecursionDFSIterator(container, containers, depth, currentTransform);
const marks = []; // list of vertical lines for the dimension
for (const {
@ -457,7 +460,7 @@ function AddVerticalBorrowerDimension(
yEnd={next}
text={value.toFixed(0)}
scale={scale}
color={color}/>);
style={style}/>);
count++;
}
}
@ -468,9 +471,9 @@ function AddVerticalSelfDimension(
container: IContainerModel,
currentTransform: [number, number],
dimensions: React.ReactNode[],
scale: number,
color: string
scale: number
): void {
const style = container.properties.dimensionOptions.selfDimensions.style;
const height = container.properties.height;
const idVert = `dim-x${xDim.toFixed(0)}-${container.properties.id}`;
let yStart = container.properties.y + currentTransform[1] + height;
@ -493,7 +496,7 @@ function AddVerticalSelfDimension(
yEnd={yEnd}
text={textVert}
scale={scale}
color={color}/>
style={style}/>
);
}
@ -502,9 +505,9 @@ function AddHorizontalSelfDimension(
container: IContainerModel,
currentTransform: [number, number],
dimensions: React.ReactNode[],
scale: number,
color: string
scale: number
): void {
const style = container.properties.dimensionOptions.selfDimensions.style;
const width = container.properties.width;
const id = `dim-y${yDim.toFixed(0)}-${container.properties.id}`;
const xStart = container.properties.x + currentTransform[0];
@ -522,7 +525,7 @@ function AddHorizontalSelfDimension(
yEnd={yDim}
text={text}
scale={scale}
color={color}/>
style={style}/>
);
}
@ -531,9 +534,9 @@ function AddHorizontalSelfMarginsDimension(
container: IContainerModel,
currentTransform: [number, number],
dimensions: React.ReactNode[],
scale: number,
color: string
scale: number
): void {
const style = container.properties.dimensionOptions.selfMarginsDimensions.style;
const left = container.properties.margin.left;
if (left != null) {
const id = `dim-y-margin-left${yDim.toFixed(0)}-${container.properties.id}`;
@ -552,7 +555,7 @@ function AddHorizontalSelfMarginsDimension(
yEnd={yDim}
text={text}
scale={scale}
color={color}/>
style={style}/>
);
}
@ -574,7 +577,7 @@ function AddHorizontalSelfMarginsDimension(
yEnd={yDim}
text={text}
scale={scale}
color={color}/>
style={style}/>
);
}
}
@ -585,9 +588,9 @@ function AddVerticalSelfMarginDimension(
container: IContainerModel,
currentTransform: [number, number],
dimensions: React.ReactNode[],
scale: number,
color: string
scale: number
): void {
const style = container.properties.dimensionOptions.selfMarginsDimensions.style;
const top = container.properties.margin.top;
if (top != null) {
const idVert = `dim-x-margin-top${xDim.toFixed(0)}-${container.properties.id}`;
@ -611,7 +614,7 @@ function AddVerticalSelfMarginDimension(
yEnd={yEnd}
text={textVert}
scale={scale}
color={color}/>
style={style}/>
);
}
const bottom = container.properties.margin.bottom;
@ -637,7 +640,7 @@ function AddVerticalSelfMarginDimension(
yEnd={yEnd}
text={textVert}
scale={scale}
color={color}/>
style={style}/>
);
}
}

View file

@ -1,10 +1,9 @@
import * as React from 'react';
import { ReactSVGPanZoom, type Tool, TOOL_PAN, type Value } from 'react-svg-pan-zoom';
import { Container } from './Elements/Container';
import { type IContainerModel } from '../../Interfaces/IContainerModel';
import { IContainerModel } from '../../Interfaces/IContainerModel';
import { SelectorContainer } from './Elements/SelectorContainer/SelectorContainer';
import { DepthDimensionLayer } from './Elements/DepthDimensionLayer';
import { MAX_FRAMERATE, SHOW_DIMENSIONS_PER_DEPTH } from '../../utils/default';
import { MAX_FRAMERATE } from '../../utils/default';
import { SymbolLayer } from './Elements/SymbolLayer';
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
import { DimensionLayer } from './Elements/DimensionLayer';
@ -121,9 +120,6 @@ export function SVG(props: ISVGProps): JSX.Element {
>
<svg {...properties}>
{children}
{SHOW_DIMENSIONS_PER_DEPTH
? <DepthDimensionLayer containers={props.containers} scale={scale} roots={props.children} />
: null}
<DimensionLayer containers={props.containers} symbols={props.symbols} scale={scale} root={props.children} />
<SymbolLayer scale={scale} symbols={props.symbols} />
<Selector />

View file

@ -24,9 +24,16 @@ export enum PropertyType {
* Dimension options
*/
SelfDimension,
SelfMarginDimension,
ChildrenDimensions,
DimensionWithMarks,
DimensionOptions
SelfDimensionStyle,
SelfMarginDimension,
SelfMarginDimensionStyle,
ChildrenDimensions,
ChildrenDimensionsStyle,
DimensionWithMarks,
DimensionWithMarksStyle,
DimensionOptions
}

View file

@ -1,12 +1,12 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { AddMethod } from '../Enums/AddMethod';
import { PositionReference } from '../Enums/PositionReference';
import { IAction } from './IAction';
import { IMargin } from './IMargin';
import { Orientation } from '../Enums/Orientation';
import { IKeyValue } from './IKeyValue';
import { IStyle } from './IStyle';
import { IDimensions } from './IDimensions';
import { type AddMethod } from '../Enums/AddMethod';
import { type PositionReference } from '../Enums/PositionReference';
import { type IAction } from './IAction';
import { type IMargin } from './IMargin';
import { type Orientation } from '../Enums/Orientation';
import { type IKeyValue } from './IKeyValue';
import { type IStyle } from './IStyle';
import { type IDimensions } from './IDimensions';
/** Model of available container used in application configuration */
export interface IAvailableContainer {

View file

@ -1,10 +1,9 @@
import { Position } from '../Enums/Position';
import { type Position } from '../Enums/Position';
import { type IDimensionStyle } from './IDimensionStyle';
export interface IDimensionOptions {
positions: Position[]
/**
* Stroke color
*/
color: string
style: IDimensionStyle
}

View file

@ -0,0 +1,12 @@
export interface IDimensionStyle {
/**
* Stroke color
*/
color?: string
/** stroke-width */
width?: number
/** stroke-dasharray */
dashArray?: string
}

View file

@ -1,4 +1,4 @@
import { IAvailableSymbol } from './IAvailableSymbol';
import { type IAvailableSymbol } from './IAvailableSymbol';
export interface ISymbolModel {
/** Identifier */

View file

@ -59,11 +59,14 @@
"@ContainerAlignmentInput": "Alignment",
"@ContainerAlignWithSymbol": "Align to symbol",
"@ContainerDimensions": "Dimensions",
"@ContainerShowDimension": "Show Dimension",
"@ContainerShowChildrenDimension": "Show surrounding dimension of children",
"@ContainerShowDimension": "Show dimensions",
"@ContainerShowChildrenDimension": "Show surrounding dimensions of children",
"@ContainerMarkPosition": "Mark the position for the parents",
"@ContainerShowDimensionWithMarks": "Show dimension with marked children",
"@ContainerShowDimensionWithMarks": "Show dimensions with marked children",
"@ContainerShowMarginsDimension": "Show margins dimensions",
"@ContainerStyle": "Style",
"@StyleStrokeColor": "Stroke Color",
"@StyleStrokeDashArray": "Stroke Dash Array",
"@StyleStroke": "Stroke",
"@StyleStrokeOpacity": "Stroke Opacity",
"@StyleStrokeWidth": "Stroke Width",

View file

@ -63,7 +63,10 @@
"@ContainerShowChildrenDimension": "Afficher les cotations englobante des enfants",
"@ContainerMarkPosition": "Marquer la position pour les parents",
"@ContainerShowDimensionWithMarks": "Afficher les cotations avec les enfants marqués",
"@ContainerShowMarginsDimension": "Afficher les cotations des marges",
"@ContainerStyle": "Style",
"@StyleStrokeColor": "Couleur du tracé",
"@StyleStrokeDashArray": "Tableau de traits",
"@StyleStroke": "Tracé",
"@StyleStrokeOpacity": "Opacité du tracé",
"@StyleStrokeWidth": "Epaisseur du tracé",

View file

@ -1,13 +1,14 @@
import { PositionReference } from '../Enums/PositionReference';
import { IAvailableContainer } from '../Interfaces/IAvailableContainer';
import { IAvailableSymbol } from '../Interfaces/IAvailableSymbol';
import { IConfiguration } from '../Interfaces/IConfiguration';
import { ContainerModel, IContainerModel } from '../Interfaces/IContainerModel';
import { IContainerProperties } from '../Interfaces/IContainerProperties';
import { IEditorState } from '../Interfaces/IEditorState';
import { ISymbolModel } from '../Interfaces/ISymbolModel';
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';
/// EDITOR DEFAULTS ///
@ -65,7 +66,6 @@ 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 SHOW_DIMENSIONS_PER_DEPTH = false;
export const DIMENSION_MARGIN = 50;
export const SYMBOL_MARGIN = 25;
export const NOTCHES_LENGTH = 10;
@ -187,6 +187,16 @@ const DEFAULT_CONTAINER_STYLE = {
strokeWidth: 2
};
export const DEFAULT_DIMENSION_STYLE = {
color: '#000000',
width: 2
};
export const DEFAULT_DIMENSION_OPTION: IDimensionOptions = {
positions: [],
style: DEFAULT_DIMENSION_STYLE
};
/**
* Default Main container properties
*/
@ -211,23 +221,11 @@ export const DEFAULT_MAINCONTAINER_PROPS: IContainerProperties = {
positionReference: PositionReference.TopLeft,
hideChildrenInTreeview: false,
dimensionOptions: {
childrenDimensions: {
color: '#000000',
positions: []
},
selfDimensions: {
color: '#000000',
positions: []
},
selfMarginsDimensions: {
color: '#000000',
positions: []
},
childrenDimensions: clone(DEFAULT_DIMENSION_OPTION),
selfDimensions: clone(DEFAULT_DIMENSION_OPTION),
selfMarginsDimensions: clone(DEFAULT_DIMENSION_OPTION),
markPosition: [],
dimensionWithMarks: {
color: '#000000',
positions: []
}
dimensionWithMarks: clone(DEFAULT_DIMENSION_OPTION)
},
warning: '',
style: DEFAULT_CONTAINER_STYLE
@ -276,21 +274,21 @@ export function GetDefaultContainerProps(type: string,
hideChildrenInTreeview: containerConfig.HideChildrenInTreeview ?? false,
dimensionOptions: {
childrenDimensions: {
color: containerConfig.DimensionOptions?.childrenDimensions.color ?? '#000000',
positions: containerConfig.DimensionOptions?.childrenDimensions.positions ?? []
positions: containerConfig.DimensionOptions?.childrenDimensions.positions ?? [],
style: containerConfig.DimensionOptions?.dimensionWithMarks.style ?? clone(DEFAULT_DIMENSION_STYLE)
},
selfDimensions: {
color: containerConfig.DimensionOptions?.selfDimensions.color ?? '#000000',
positions: containerConfig.DimensionOptions?.selfDimensions.positions ?? []
positions: containerConfig.DimensionOptions?.selfDimensions.positions ?? [],
style: containerConfig.DimensionOptions?.dimensionWithMarks.style ?? clone(DEFAULT_DIMENSION_STYLE)
},
selfMarginsDimensions: {
color: containerConfig.DimensionOptions?.selfMarginsDimensions.color ?? '#000000',
positions: containerConfig.DimensionOptions?.selfMarginsDimensions.positions ?? []
positions: containerConfig.DimensionOptions?.selfMarginsDimensions.positions ?? [],
style: containerConfig.DimensionOptions?.dimensionWithMarks.style ?? clone(DEFAULT_DIMENSION_STYLE)
},
markPosition: containerConfig.DimensionOptions?.markPosition ?? [],
dimensionWithMarks: {
color: containerConfig.DimensionOptions?.dimensionWithMarks.color ?? '#000000',
positions: containerConfig.DimensionOptions?.dimensionWithMarks.positions ?? []
positions: containerConfig.DimensionOptions?.dimensionWithMarks.positions ?? [],
style: containerConfig.DimensionOptions?.dimensionWithMarks.style ?? clone(DEFAULT_DIMENSION_STYLE)
}
},
warning: '',
@ -317,3 +315,10 @@ export function GetDefaultSymbolModel(name: string,
showDimension: false
};
}
/**
* Macro function for JSON.parse(JSON.stringify(obj))
*/
function clone<T>(object: T): T {
return JSON.parse(JSON.stringify(object));
}