diff --git a/src/Components/ContainerProperties/ContainerForm.tsx b/src/Components/ContainerProperties/ContainerForm.tsx index 487b302..043a96c 100644 --- a/src/Components/ContainerProperties/ContainerForm.tsx +++ b/src/Components/ContainerProperties/ContainerForm.tsx @@ -1,4 +1,5 @@ -import { Bars3BottomLeftIcon, Bars3CenterLeftIcon, Bars3Icon, Bars3BottomRightIcon, Bars2Icon, ViewColumnsIcon } from '@heroicons/react/24/outline'; +import { Bars3BottomLeftIcon, Bars3CenterLeftIcon, Bars3Icon, Bars3BottomRightIcon, Bars2Icon } from '@heroicons/react/24/outline'; +import { FlagIcon, ViewColumnsIcon } from '@heroicons/react/20/solid'; import * as React from 'react'; import { PropertyType } from '../../Enums/PropertyType'; import { PositionReference } from '../../Enums/PositionReference'; @@ -12,11 +13,12 @@ import { RadioGroupButtons } from '../RadioGroupButtons/RadioGroupButtons'; import { Select } from '../Select/Select'; import { ToggleButton, ToggleType } from '../ToggleButton/ToggleButton'; import { Orientation } from '../../Enums/Orientation'; +import { EnumCheckboxGroupButtons } from '../EnumCheckboxGroupButtons/EnumCheckboxGroupButtons'; interface IContainerFormProps { properties: IContainerProperties symbols: Map - onChange: (key: string, value: string | number | boolean, type?: PropertyType) => void + onChange: (key: string, value: string | number | boolean | number[], type?: PropertyType) => void } function GetCSSInputs(properties: IContainerProperties, @@ -284,14 +286,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element { { SHOW_BORROWER_DIMENSIONS && <> - props.onChange('markPositionToDimensionBorrower', event.target.checked)} /> + + + + ), + value: Orientation.Horizontal + }, + { + key: 'mark-position-vertical', + text: ( +
+ +
+ ), + value: Orientation.Vertical + } + ]} + onChange={(newSelectedValues) => { + props.onChange('markPositionToDimensionBorrower', newSelectedValues); + }} + />; +} + function OrientationSelector(props: IContainerFormProps): JSX.Element { return - + ), value: Orientation.Horizontal.toString() @@ -330,7 +359,7 @@ function OrientationSelector(props: IContainerFormProps): JSX.Element { key: 'orientation-vertical', text: (
- +
), value: Orientation.Vertical.toString() diff --git a/src/Components/ContainerProperties/ContainerProperties.tsx b/src/Components/ContainerProperties/ContainerProperties.tsx index 753695b..d0183c6 100644 --- a/src/Components/ContainerProperties/ContainerProperties.tsx +++ b/src/Components/ContainerProperties/ContainerProperties.tsx @@ -7,7 +7,7 @@ import { ContainerForm } from './ContainerForm'; interface IPropertiesProps { properties?: IContainerProperties symbols: Map - onChange: (key: string, value: string | number | boolean, type?: PropertyType) => void + onChange: (key: string, value: string | number | boolean | number[], type?: PropertyType) => void } export function Properties(props: IPropertiesProps): JSX.Element { diff --git a/src/Components/Editor/Actions/ContainerOperations.ts b/src/Components/Editor/Actions/ContainerOperations.ts index ac97f02..255e655 100644 --- a/src/Components/Editor/Actions/ContainerOperations.ts +++ b/src/Components/Editor/Actions/ContainerOperations.ts @@ -152,7 +152,7 @@ function UnlinkContainerFromSymbols(symbols: Map, containe */ export function OnPropertyChange( key: string, - value: string | number | boolean, + value: string | number | boolean | number[], type: PropertyType = PropertyType.Simple, selected: IContainerModel | undefined, fullHistory: IHistoryState[], @@ -247,7 +247,7 @@ export function SortChildren(parentClone: IContainerModel | null | undefined): v */ function SetContainer( container: ContainerModel, - key: string, value: string | number | boolean, + key: string, value: string | number | boolean | number[], type: PropertyType, symbols: Map ): void { @@ -282,7 +282,7 @@ function SetContainer( * @param value Value of the property * @param type Type of the property */ -function AssignProperty(container: ContainerModel, key: string, value: string | number | boolean, type: PropertyType): void { +function AssignProperty(container: ContainerModel, key: string, value: string | number | boolean | number[], type: PropertyType): void { switch (type) { case PropertyType.Style: (container.properties.style as any)[key] = value; diff --git a/src/Components/ElementsSidebar/ElementsSidebar.tsx b/src/Components/ElementsSidebar/ElementsSidebar.tsx index 7fef052..ad52c3c 100644 --- a/src/Components/ElementsSidebar/ElementsSidebar.tsx +++ b/src/Components/ElementsSidebar/ElementsSidebar.tsx @@ -15,7 +15,7 @@ interface IElementsSidebarProps { selectedContainer: IContainerModel | undefined onPropertyChange: ( key: string, - value: string | number | boolean, + value: string | number | boolean | number[], type?: PropertyType ) => void selectContainer: (containerId: string) => void diff --git a/src/Components/EnumCheckboxGroupButtons/EnumCheckboxGroupButtons.tsx b/src/Components/EnumCheckboxGroupButtons/EnumCheckboxGroupButtons.tsx new file mode 100644 index 0000000..59053b6 --- /dev/null +++ b/src/Components/EnumCheckboxGroupButtons/EnumCheckboxGroupButtons.tsx @@ -0,0 +1,86 @@ +import * as React from 'react'; +import { IInputGroup } from '../../Interfaces/IInputGroup'; + +interface ICheckboxGroupButtonsProps { + name: string + selectedValues: number[] + inputClassName: string + labelText: string + inputGroups: IEnumCheckboxInputGroup[] + colQty: number + onChange: (newSelectedValues: number[]) => void +} + +interface IEnumCheckboxInputGroup extends Omit { + value: number +} + +// Use whole class name for react to preparse +const GRID_COLS = [ + 'grid-cols-none', + 'grid-cols-1', + 'grid-cols-2', + 'grid-cols-3', + 'grid-cols-4', + 'grid-cols-5', + 'grid-cols-6', + 'grid-cols-7', + 'grid-cols-8', + 'grid-cols-9', + 'grid-cols-10', + 'grid-cols-11', + 'grid-cols-12' +]; + +export function EnumCheckboxGroupButtons(props: ICheckboxGroupButtonsProps): JSX.Element { + const selectedOptions = new Set(props.selectedValues); + const inputGroups = props.inputGroups.map((inputGroup) => ( +
+ { + const newSelectedValues = SetChecked(Number(event.target.value), event.target.checked); + props.onChange(newSelectedValues); + }} /> + +
+ )); + + const gridColsClass = GRID_COLS[props.colQty]; + + return ( + <> + +
+ {inputGroups} +
+ + ); + + function IsChecked(inputGroup: IEnumCheckboxInputGroup): boolean { + return selectedOptions.has(inputGroup.value); + } + + /** + * Sedt an option by using a bitwise operation and returns the new selected values + * example: set the 4th option to 0: (1001) xor (1 << 3) => 0001 + * @param selectedValue The option to set + * @returns The new selected values + */ + function SetChecked(selectedValue: number, isChecked: boolean): number[] { + isChecked ? selectedOptions.add(selectedValue) : selectedOptions.delete(selectedValue); + return [...selectedOptions]; + } +} diff --git a/src/Components/RadioGroupButtons/RadioGroupButtons.tsx b/src/Components/RadioGroupButtons/RadioGroupButtons.tsx index 8ff073d..751da23 100644 --- a/src/Components/RadioGroupButtons/RadioGroupButtons.tsx +++ b/src/Components/RadioGroupButtons/RadioGroupButtons.tsx @@ -3,8 +3,7 @@ import { IInputGroup } from '../../Interfaces/IInputGroup'; interface IRadioGroupButtonsProps { name: string - value?: string - defaultValue?: string + value: string inputClassName: string labelText: string inputGroups: IInputGroup[] @@ -30,44 +29,23 @@ const GRID_COLS = [ ]; export function RadioGroupButtons(props: IRadioGroupButtonsProps): JSX.Element { - let inputGroups; - if (props.value !== undefined) { - // dynamic - inputGroups = props.inputGroups.map((inputGroup) => ( -
- - -
+ const inputGroups = props.inputGroups.map((inputGroup) => ( +
+ + +
- )); - } else { - // static - inputGroups = props.inputGroups.map((inputGroup) => ( -
- - -
- )); - } + )); const gridColsClass = GRID_COLS[props.colQty]; @@ -76,7 +54,7 @@ export function RadioGroupButtons(props: IRadioGroupButtonsProps): JSX.Element { -
{inputGroups} diff --git a/src/Components/SVG/Elements/DimensionLayer.tsx b/src/Components/SVG/Elements/DimensionLayer.tsx index 4d677b3..0224c32 100644 --- a/src/Components/SVG/Elements/DimensionLayer.tsx +++ b/src/Components/SVG/Elements/DimensionLayer.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { Orientation } from '../../../Enums/Orientation'; import { ContainerModel, IContainerModel } from '../../../Interfaces/IContainerModel'; import { DIMENSION_MARGIN, SHOW_BORROWER_DIMENSIONS, SHOW_CHILDREN_DIMENSIONS, SHOW_SELF_DIMENSIONS } from '../../../utils/default'; import { MakeRecursionDFSIterator, Pairwise } from '../../../utils/itertools'; @@ -37,7 +38,7 @@ function Dimensions({ root, scale }: IDimensionLayerProps): React.ReactNode[] { AddBorrowerDimension(containerBottomDim, containerRightDim, depth, scale, container, currentTransform, dimensions); } - if (SHOW_CHILDREN_DIMENSIONS && container.properties.showChildrenDimensions && container.children.length > 0) { + if (SHOW_CHILDREN_DIMENSIONS && container.properties.showChildrenDimensions && container.children.length > 1) { AddChildrenDimension(container, currentTransform, dimensions, containerBottomDim, containerRightDim, scale); } } @@ -171,7 +172,8 @@ function AddHorizontalBorrowerDimension( for (const { container: childContainer, currentTransform: childCurrentTransform } of it) { - if (!childContainer.properties.markPositionToDimensionBorrower) { + const isHidden = !childContainer.properties.markPositionToDimensionBorrower.includes(Orientation.Horizontal); + if (isHidden) { continue; } @@ -223,7 +225,8 @@ function AddVerticalBorrowerDimension( for (const { container: childContainer, currentTransform: childCurrentTransform } of it) { - if (!childContainer.properties.markPositionToDimensionBorrower) { + const isHidden = !childContainer.properties.markPositionToDimensionBorrower.includes(Orientation.Vertical); + if (isHidden) { continue; } diff --git a/src/Components/UI/UI.tsx b/src/Components/UI/UI.tsx index 86a3ede..7d6dc60 100644 --- a/src/Components/UI/UI.tsx +++ b/src/Components/UI/UI.tsx @@ -25,7 +25,7 @@ interface IUIProps { categories: ICategory[] selectContainer: (containerId: string) => void deleteContainer: (containerId: string) => void - onPropertyChange: (key: string, value: string | number | boolean, type?: PropertyType) => void + onPropertyChange: (key: string, value: string | number | boolean | number[], type?: PropertyType) => void addContainer: (type: string) => void addContainerAt: (index: number, type: string, parent: string) => void addSymbol: (type: string) => void diff --git a/src/Interfaces/IAvailableContainer.ts b/src/Interfaces/IAvailableContainer.ts index 543c4df..af7a64a 100644 --- a/src/Interfaces/IAvailableContainer.ts +++ b/src/Interfaces/IAvailableContainer.ts @@ -120,7 +120,7 @@ export interface IAvailableContainer { /** * if true, allows a parent dimension borrower to uses its x coordinate for as a reference point for a dimension */ - MarkPositionToDimensionBorrower?: boolean + MarkPositionToDimensionBorrower?: Orientation[] /** * if true, show a dimension from the edge of the container to end diff --git a/src/Interfaces/IContainerProperties.ts b/src/Interfaces/IContainerProperties.ts index d394282..472a3b2 100644 --- a/src/Interfaces/IContainerProperties.ts +++ b/src/Interfaces/IContainerProperties.ts @@ -82,7 +82,7 @@ export interface IContainerProperties { * if true, allows a parent dimension borrower to borrow its x coordinate * as a reference point for a dimension */ - markPositionToDimensionBorrower: boolean + markPositionToDimensionBorrower: Orientation[] /** * if true, show a dimension from the edge of the container to end diff --git a/src/utils/default.ts b/src/utils/default.ts index f798371..d89fd2e 100644 --- a/src/utils/default.ts +++ b/src/utils/default.ts @@ -191,7 +191,7 @@ export const DEFAULT_MAINCONTAINER_PROPS: IContainerProperties = { showChildrenDimensions: true, // TODO: put the dimension at the top (see pdf) showSelfDimensions: true, // TODO: put the dimension at the bottom (see pdf) isDimensionBorrower: true, // second dimensions from the bottom - markPositionToDimensionBorrower: false, + markPositionToDimensionBorrower: [], warning: '', style: { stroke: 'black', @@ -242,7 +242,7 @@ export function GetDefaultContainerProps(type: string, hideChildrenInTreeview: containerConfig.HideChildrenInTreeview ?? false, showChildrenDimensions: containerConfig.ShowChildrenDimensions ?? false, showSelfDimensions: containerConfig.ShowSelfDimensions ?? false, - markPositionToDimensionBorrower: containerConfig.MarkPositionToDimensionBorrower ?? false, + markPositionToDimensionBorrower: containerConfig.MarkPositionToDimensionBorrower ?? [], isDimensionBorrower: containerConfig.IsDimensionBorrower ?? false, warning: '', customSVG: containerConfig.CustomSVG, diff --git a/test-server/node-http.js b/test-server/node-http.js index 4868d3b..07efe7f 100644 --- a/test-server/node-http.js +++ b/test-server/node-http.js @@ -157,7 +157,7 @@ const GetSVGLayoutConfiguration = () => { Type: 'Montant', Width: 10, PositionReference: 4, - MarkPositionToDimensionBorrower: true, + MarkPositionToDimensionBorrower: [0], Style: { fillOpacity: 0, strokeWidth: 2, @@ -170,7 +170,7 @@ const GetSVGLayoutConfiguration = () => { Height: 10, PositionReference: 4, Orientation: 1, - MarkPositionToDimensionBorrower: true, + MarkPositionToDimensionBorrower: [1], Style: { fillOpacity: 0, strokeWidth: 2, @@ -182,7 +182,7 @@ const GetSVGLayoutConfiguration = () => { Type: 'Dilatation', Width: 4, PositionReference: 1, - MarkPositionToDimensionBorrower: true, + MarkPositionToDimensionBorrower: [0], Style: { fillOpacity: 0, strokeWidth: 2,