Final fix for XPositionReference : We are now lying to the user in the form. The transformation is applied to the value that is shown but the transformation is restored for the computing afterward

This commit is contained in:
Eric NGUYEN 2022-08-16 16:34:32 +02:00
parent 7014f520b9
commit 1622816035
6 changed files with 59 additions and 45 deletions

View file

@ -7,7 +7,7 @@ import { getCurrentHistory } from './Editor';
import IProperties from '../../Interfaces/IProperties';
import { AddMethod } from '../../Enums/AddMethod';
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { transformPosition } from '../SVG/Elements/Container';
import { transformX } from '../SVG/Elements/Container';
import { XPositionReference } from '../../Enums/XPositionReference';
/**
@ -267,14 +267,7 @@ function ApplyAddMethod(index: number, containerConfig: IAvailableContainer, par
const lastChild: IContainerModel | undefined = parent.children.at(index - 1);
if (lastChild !== undefined) {
const [transformedX] = transformPosition(
lastChild.properties.x,
lastChild.properties.y,
lastChild.properties.width,
lastChild.properties.XPositionReference
);
x += transformedX + lastChild.properties.width;
x += (lastChild.properties.x + lastChild.properties.width);
}
}
return x;

View file

@ -6,6 +6,7 @@ import { getCurrentHistory } from './Editor';
import { RecalculatePhysics } from './Behaviors/RigidBodyBehaviors';
import { INPUT_TYPES } from '../Properties/PropertiesInputTypes';
import { ImposePosition } from './Behaviors/AnchorBehaviors';
import { restoreX } from '../SVG/Elements/Container';
/**
* Handled the property change event in the properties form
@ -39,13 +40,9 @@ export function OnPropertyChange(
if (isStyle) {
(container.properties.style as any)[key] = value;
} else {
if (INPUT_TYPES[key] === 'number') {
(container.properties as any)[key] = Number(value);
} else {
(container.properties as any)[key] = value;
}
}
if (container.properties.isAnchor) {
ImposePosition(container);
@ -104,10 +101,33 @@ export function OnPropertiesSubmit(
}
if (input instanceof HTMLInputElement) {
(container.properties as any)[property] = input.value;
if (INPUT_TYPES[property] === 'number') {
(container.properties as any)[property] = Number(input.value);
if (property === 'x') {
// Hardcoded fix for XPositionReference
const inputWidth: HTMLInputElement | null = (event.target as HTMLFormElement).querySelector('#width');
const inputRadio: HTMLDivElement | null = (event.target as HTMLFormElement).querySelector('#XPositionReference');
if (inputWidth === null || inputRadio === null) {
throw new Error('[OnPropertiesSubmit] Missing inputs for width or XPositionReference');
}
const radiobutton: HTMLInputElement | null = inputRadio.querySelector('input[name="XPositionReference"]:checked');
if (radiobutton === null) {
throw new Error('[OnPropertiesSubmit] Missing inputs for XPositionReference');
}
const x = restoreX(Number(input.value), Number(inputWidth.value), Number(radiobutton.value));
(container.properties as any)[property] = x;
continue;
}
(container.properties as any)[property] = Number(input.value);
continue;
}
(container.properties as any)[property] = input.value;
} else if (input instanceof HTMLDivElement) {
const radiobutton: HTMLInputElement | null = input.querySelector(`input[name="${property}"]:checked`);
@ -115,10 +135,12 @@ export function OnPropertiesSubmit(
continue;
}
(container.properties as any)[property] = radiobutton.value;
if (INPUT_TYPES[property] === 'number') {
(container.properties as any)[property] = Number(radiobutton.value);
continue;
}
(container.properties as any)[property] = radiobutton.value;
}
}

View file

@ -4,6 +4,7 @@ import { XPositionReference } from '../../Enums/XPositionReference';
import IProperties from '../../Interfaces/IProperties';
import { InputGroup } from '../InputGroup/InputGroup';
import { RadioGroupButtons } from '../RadioGroupButtons/RadioGroupButtons';
import { restoreX, transformX } from '../SVG/Elements/Container';
interface IDynamicFormProps {
properties: IProperties
@ -57,8 +58,8 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
labelClassName=''
inputClassName=''
type='number'
value={props.properties.x.toString()}
onChange={(event) => props.onChange('x', event.target.value)}
value={transformX(props.properties.x, props.properties.width, props.properties.XPositionReference).toString()}
onChange={(event) => props.onChange('x', restoreX(Number(event.target.value), props.properties.width, props.properties.XPositionReference))}
/>
<InputGroup
labelText='y'
@ -67,7 +68,7 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
inputClassName=''
type='number'
value={props.properties.y.toString()}
onChange={(event) => props.onChange('y', event.target.value)}
onChange={(event) => props.onChange('y', Number(event.target.value))}
/>
<InputGroup
labelText='Width'
@ -76,7 +77,7 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
inputClassName=''
type='number'
value={props.properties.width.toString()}
onChange={(event) => props.onChange('width', event.target.value)}
onChange={(event) => props.onChange('width', Number(event.target.value))}
/>
<InputGroup
labelText='Height'
@ -85,7 +86,7 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
inputClassName=''
type='number'
value={props.properties.height.toString()}
onChange={(event) => props.onChange('height', event.target.value)}
onChange={(event) => props.onChange('height', Number(event.target.value))}
/>
<InputGroup
labelText='Rigid'
@ -136,7 +137,7 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
value: XPositionReference.Right.toString()
}
]}
onChange={(event) => props.onChange('XPositionReference', event.target.value)}
onChange={(event) => props.onChange('XPositionReference', Number(event.target.value))}
/>
{ getCSSInputs(props.properties, props.onChange) }
</div>

View file

@ -4,6 +4,7 @@ import { XPositionReference } from '../../Enums/XPositionReference';
import IProperties from '../../Interfaces/IProperties';
import { InputGroup } from '../InputGroup/InputGroup';
import { RadioGroupButtons } from '../RadioGroupButtons/RadioGroupButtons';
import { transformX } from '../SVG/Elements/Container';
interface IStaticFormProps {
properties: IProperties
@ -57,7 +58,7 @@ const StaticForm: React.FunctionComponent<IStaticFormProps> = (props) => {
labelClassName=''
inputClassName=''
type='number'
defaultValue={props.properties.x.toString()}
defaultValue={transformX(props.properties.x, props.properties.width, props.properties.XPositionReference).toString()}
/>
<InputGroup
labelText='y'

View file

@ -18,13 +18,7 @@ export const Container: React.FC<IContainerProps> = (props: IContainerProps) =>
const xText = props.model.properties.width / 2;
const yText = props.model.properties.height / 2;
const [transformedX, transformedY] = transformPosition(
props.model.properties.x,
props.model.properties.y,
props.model.properties.width,
props.model.properties.XPositionReference
);
const transform = `translate(${transformedX}, ${transformedY})`;
const transform = `translate(${props.model.properties.x}, ${props.model.properties.y})`;
// g style
const defaultStyle: React.CSSProperties = {
@ -107,17 +101,17 @@ function GetChildrenDimensionProps(props: IContainerProps, dimensionMargin: numb
const childrenId = `dim-children-${props.model.properties.id}`;
const lastChild = props.model.children[props.model.children.length - 1];
let xChildrenStart = lastChild.properties.x;
let xChildrenEnd = lastChild.properties.x;
let xChildrenStart = transformX(lastChild.properties.x, lastChild.properties.width, lastChild.properties.XPositionReference);
let xChildrenEnd = transformX(lastChild.properties.x, lastChild.properties.width, lastChild.properties.XPositionReference);
// Find the min and max
for (let i = props.model.children.length - 2; i >= 0; i--) {
const child = props.model.children[i];
const left = child.properties.x;
const left = transformX(child.properties.x, child.properties.width, child.properties.XPositionReference);
if (left < xChildrenStart) {
xChildrenStart = left;
}
const right = child.properties.x;
const right = transformX(child.properties.x, child.properties.width, child.properties.XPositionReference);
if (right > xChildrenEnd) {
xChildrenEnd = right;
}
@ -128,12 +122,22 @@ function GetChildrenDimensionProps(props: IContainerProps, dimensionMargin: numb
return { childrenId, xChildrenStart, xChildrenEnd, yChildren, textChildren };
}
export function transformPosition(x: number, y: number, width: number, xPositionReference = XPositionReference.Left): [number, number] {
export function transformX(x: number, width: number, xPositionReference = XPositionReference.Left): number {
let transformedX = x;
if (xPositionReference === XPositionReference.Center) {
transformedX += width / 2;
} else if (xPositionReference === XPositionReference.Right) {
transformedX += width;
}
return transformedX;
}
export function restoreX(x: number, width: number, xPositionReference = XPositionReference.Left): number {
let transformedX = x;
if (xPositionReference === XPositionReference.Center) {
transformedX -= width / 2;
} else if (xPositionReference === XPositionReference.Right) {
transformedX -= width;
}
return [transformedX, y];
return transformedX;
}

View file

@ -1,7 +1,6 @@
import * as React from 'react';
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { getAbsolutePosition } from '../../../utils/itertools';
import { transformPosition } from './Container';
interface ISelectorProps {
selected: IContainerModel | null
@ -16,12 +15,6 @@ export const Selector: React.FC<ISelectorProps> = (props) => {
}
const [x, y] = getAbsolutePosition(props.selected);
const [transformedX, transformedY] = transformPosition(
x,
y,
props.selected.properties.width,
props.selected.properties.XPositionReference
);
const [width, height] = [
props.selected.properties.width,
props.selected.properties.height
@ -38,8 +31,8 @@ export const Selector: React.FC<ISelectorProps> = (props) => {
return (
<rect
x={transformedX}
y={transformedY}
x={x}
y={y}
width={width}
height={height}
style={style}