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:
parent
7014f520b9
commit
1622816035
6 changed files with 59 additions and 45 deletions
|
@ -7,7 +7,7 @@ import { getCurrentHistory } from './Editor';
|
||||||
import IProperties from '../../Interfaces/IProperties';
|
import IProperties from '../../Interfaces/IProperties';
|
||||||
import { AddMethod } from '../../Enums/AddMethod';
|
import { AddMethod } from '../../Enums/AddMethod';
|
||||||
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
|
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
|
||||||
import { transformPosition } from '../SVG/Elements/Container';
|
import { transformX } from '../SVG/Elements/Container';
|
||||||
import { XPositionReference } from '../../Enums/XPositionReference';
|
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);
|
const lastChild: IContainerModel | undefined = parent.children.at(index - 1);
|
||||||
|
|
||||||
if (lastChild !== undefined) {
|
if (lastChild !== undefined) {
|
||||||
const [transformedX] = transformPosition(
|
x += (lastChild.properties.x + lastChild.properties.width);
|
||||||
lastChild.properties.x,
|
|
||||||
lastChild.properties.y,
|
|
||||||
lastChild.properties.width,
|
|
||||||
lastChild.properties.XPositionReference
|
|
||||||
);
|
|
||||||
|
|
||||||
x += transformedX + lastChild.properties.width;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { getCurrentHistory } from './Editor';
|
||||||
import { RecalculatePhysics } from './Behaviors/RigidBodyBehaviors';
|
import { RecalculatePhysics } from './Behaviors/RigidBodyBehaviors';
|
||||||
import { INPUT_TYPES } from '../Properties/PropertiesInputTypes';
|
import { INPUT_TYPES } from '../Properties/PropertiesInputTypes';
|
||||||
import { ImposePosition } from './Behaviors/AnchorBehaviors';
|
import { ImposePosition } from './Behaviors/AnchorBehaviors';
|
||||||
|
import { restoreX } from '../SVG/Elements/Container';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handled the property change event in the properties form
|
* Handled the property change event in the properties form
|
||||||
|
@ -40,11 +41,7 @@ export function OnPropertyChange(
|
||||||
if (isStyle) {
|
if (isStyle) {
|
||||||
(container.properties.style as any)[key] = value;
|
(container.properties.style as any)[key] = value;
|
||||||
} else {
|
} else {
|
||||||
if (INPUT_TYPES[key] === 'number') {
|
(container.properties as any)[key] = value;
|
||||||
(container.properties as any)[key] = Number(value);
|
|
||||||
} else {
|
|
||||||
(container.properties as any)[key] = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container.properties.isAnchor) {
|
if (container.properties.isAnchor) {
|
||||||
|
@ -104,10 +101,33 @@ export function OnPropertiesSubmit(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input instanceof HTMLInputElement) {
|
if (input instanceof HTMLInputElement) {
|
||||||
(container.properties as any)[property] = input.value;
|
|
||||||
if (INPUT_TYPES[property] === 'number') {
|
if (INPUT_TYPES[property] === 'number') {
|
||||||
|
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);
|
(container.properties as any)[property] = Number(input.value);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(container.properties as any)[property] = input.value;
|
||||||
} else if (input instanceof HTMLDivElement) {
|
} else if (input instanceof HTMLDivElement) {
|
||||||
const radiobutton: HTMLInputElement | null = input.querySelector(`input[name="${property}"]:checked`);
|
const radiobutton: HTMLInputElement | null = input.querySelector(`input[name="${property}"]:checked`);
|
||||||
|
|
||||||
|
@ -115,10 +135,12 @@ export function OnPropertiesSubmit(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
(container.properties as any)[property] = radiobutton.value;
|
|
||||||
if (INPUT_TYPES[property] === 'number') {
|
if (INPUT_TYPES[property] === 'number') {
|
||||||
(container.properties as any)[property] = Number(radiobutton.value);
|
(container.properties as any)[property] = Number(radiobutton.value);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(container.properties as any)[property] = radiobutton.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { XPositionReference } from '../../Enums/XPositionReference';
|
||||||
import IProperties from '../../Interfaces/IProperties';
|
import IProperties from '../../Interfaces/IProperties';
|
||||||
import { InputGroup } from '../InputGroup/InputGroup';
|
import { InputGroup } from '../InputGroup/InputGroup';
|
||||||
import { RadioGroupButtons } from '../RadioGroupButtons/RadioGroupButtons';
|
import { RadioGroupButtons } from '../RadioGroupButtons/RadioGroupButtons';
|
||||||
|
import { restoreX, transformX } from '../SVG/Elements/Container';
|
||||||
|
|
||||||
interface IDynamicFormProps {
|
interface IDynamicFormProps {
|
||||||
properties: IProperties
|
properties: IProperties
|
||||||
|
@ -57,8 +58,8 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
|
||||||
labelClassName=''
|
labelClassName=''
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='number'
|
type='number'
|
||||||
value={props.properties.x.toString()}
|
value={transformX(props.properties.x, props.properties.width, props.properties.XPositionReference).toString()}
|
||||||
onChange={(event) => props.onChange('x', event.target.value)}
|
onChange={(event) => props.onChange('x', restoreX(Number(event.target.value), props.properties.width, props.properties.XPositionReference))}
|
||||||
/>
|
/>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
labelText='y'
|
labelText='y'
|
||||||
|
@ -67,7 +68,7 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='number'
|
type='number'
|
||||||
value={props.properties.y.toString()}
|
value={props.properties.y.toString()}
|
||||||
onChange={(event) => props.onChange('y', event.target.value)}
|
onChange={(event) => props.onChange('y', Number(event.target.value))}
|
||||||
/>
|
/>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
labelText='Width'
|
labelText='Width'
|
||||||
|
@ -76,7 +77,7 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='number'
|
type='number'
|
||||||
value={props.properties.width.toString()}
|
value={props.properties.width.toString()}
|
||||||
onChange={(event) => props.onChange('width', event.target.value)}
|
onChange={(event) => props.onChange('width', Number(event.target.value))}
|
||||||
/>
|
/>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
labelText='Height'
|
labelText='Height'
|
||||||
|
@ -85,7 +86,7 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='number'
|
type='number'
|
||||||
value={props.properties.height.toString()}
|
value={props.properties.height.toString()}
|
||||||
onChange={(event) => props.onChange('height', event.target.value)}
|
onChange={(event) => props.onChange('height', Number(event.target.value))}
|
||||||
/>
|
/>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
labelText='Rigid'
|
labelText='Rigid'
|
||||||
|
@ -136,7 +137,7 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
|
||||||
value: XPositionReference.Right.toString()
|
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) }
|
{ getCSSInputs(props.properties, props.onChange) }
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { XPositionReference } from '../../Enums/XPositionReference';
|
||||||
import IProperties from '../../Interfaces/IProperties';
|
import IProperties from '../../Interfaces/IProperties';
|
||||||
import { InputGroup } from '../InputGroup/InputGroup';
|
import { InputGroup } from '../InputGroup/InputGroup';
|
||||||
import { RadioGroupButtons } from '../RadioGroupButtons/RadioGroupButtons';
|
import { RadioGroupButtons } from '../RadioGroupButtons/RadioGroupButtons';
|
||||||
|
import { transformX } from '../SVG/Elements/Container';
|
||||||
|
|
||||||
interface IStaticFormProps {
|
interface IStaticFormProps {
|
||||||
properties: IProperties
|
properties: IProperties
|
||||||
|
@ -57,7 +58,7 @@ const StaticForm: React.FunctionComponent<IStaticFormProps> = (props) => {
|
||||||
labelClassName=''
|
labelClassName=''
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='number'
|
type='number'
|
||||||
defaultValue={props.properties.x.toString()}
|
defaultValue={transformX(props.properties.x, props.properties.width, props.properties.XPositionReference).toString()}
|
||||||
/>
|
/>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
labelText='y'
|
labelText='y'
|
||||||
|
|
|
@ -18,13 +18,7 @@ export const Container: React.FC<IContainerProps> = (props: IContainerProps) =>
|
||||||
const xText = props.model.properties.width / 2;
|
const xText = props.model.properties.width / 2;
|
||||||
const yText = props.model.properties.height / 2;
|
const yText = props.model.properties.height / 2;
|
||||||
|
|
||||||
const [transformedX, transformedY] = transformPosition(
|
const transform = `translate(${props.model.properties.x}, ${props.model.properties.y})`;
|
||||||
props.model.properties.x,
|
|
||||||
props.model.properties.y,
|
|
||||||
props.model.properties.width,
|
|
||||||
props.model.properties.XPositionReference
|
|
||||||
);
|
|
||||||
const transform = `translate(${transformedX}, ${transformedY})`;
|
|
||||||
|
|
||||||
// g style
|
// g style
|
||||||
const defaultStyle: React.CSSProperties = {
|
const defaultStyle: React.CSSProperties = {
|
||||||
|
@ -107,17 +101,17 @@ function GetChildrenDimensionProps(props: IContainerProps, dimensionMargin: numb
|
||||||
const childrenId = `dim-children-${props.model.properties.id}`;
|
const childrenId = `dim-children-${props.model.properties.id}`;
|
||||||
|
|
||||||
const lastChild = props.model.children[props.model.children.length - 1];
|
const lastChild = props.model.children[props.model.children.length - 1];
|
||||||
let xChildrenStart = lastChild.properties.x;
|
let xChildrenStart = transformX(lastChild.properties.x, lastChild.properties.width, lastChild.properties.XPositionReference);
|
||||||
let xChildrenEnd = lastChild.properties.x;
|
let xChildrenEnd = transformX(lastChild.properties.x, lastChild.properties.width, lastChild.properties.XPositionReference);
|
||||||
|
|
||||||
// Find the min and max
|
// Find the min and max
|
||||||
for (let i = props.model.children.length - 2; i >= 0; i--) {
|
for (let i = props.model.children.length - 2; i >= 0; i--) {
|
||||||
const child = props.model.children[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) {
|
if (left < xChildrenStart) {
|
||||||
xChildrenStart = left;
|
xChildrenStart = left;
|
||||||
}
|
}
|
||||||
const right = child.properties.x;
|
const right = transformX(child.properties.x, child.properties.width, child.properties.XPositionReference);
|
||||||
if (right > xChildrenEnd) {
|
if (right > xChildrenEnd) {
|
||||||
xChildrenEnd = right;
|
xChildrenEnd = right;
|
||||||
}
|
}
|
||||||
|
@ -128,12 +122,22 @@ function GetChildrenDimensionProps(props: IContainerProps, dimensionMargin: numb
|
||||||
return { childrenId, xChildrenStart, xChildrenEnd, yChildren, textChildren };
|
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;
|
let transformedX = x;
|
||||||
if (xPositionReference === XPositionReference.Center) {
|
if (xPositionReference === XPositionReference.Center) {
|
||||||
transformedX -= width / 2;
|
transformedX -= width / 2;
|
||||||
} else if (xPositionReference === XPositionReference.Right) {
|
} else if (xPositionReference === XPositionReference.Right) {
|
||||||
transformedX -= width;
|
transformedX -= width;
|
||||||
}
|
}
|
||||||
return [transformedX, y];
|
return transformedX;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { getAbsolutePosition } from '../../../utils/itertools';
|
import { getAbsolutePosition } from '../../../utils/itertools';
|
||||||
import { transformPosition } from './Container';
|
|
||||||
|
|
||||||
interface ISelectorProps {
|
interface ISelectorProps {
|
||||||
selected: IContainerModel | null
|
selected: IContainerModel | null
|
||||||
|
@ -16,12 +15,6 @@ export const Selector: React.FC<ISelectorProps> = (props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const [x, y] = getAbsolutePosition(props.selected);
|
const [x, y] = getAbsolutePosition(props.selected);
|
||||||
const [transformedX, transformedY] = transformPosition(
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
props.selected.properties.width,
|
|
||||||
props.selected.properties.XPositionReference
|
|
||||||
);
|
|
||||||
const [width, height] = [
|
const [width, height] = [
|
||||||
props.selected.properties.width,
|
props.selected.properties.width,
|
||||||
props.selected.properties.height
|
props.selected.properties.height
|
||||||
|
@ -38,8 +31,8 @@ export const Selector: React.FC<ISelectorProps> = (props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<rect
|
<rect
|
||||||
x={transformedX}
|
x={x}
|
||||||
y={transformedY}
|
y={y}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
style={style}
|
style={style}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue