Compare commits
4 commits
7014f520b9
...
a36d5d79d4
Author | SHA1 | Date | |
---|---|---|---|
|
a36d5d79d4 | ||
|
e3190dfe0a | ||
|
0fcc2244bb | ||
|
1622816035 |
7 changed files with 108 additions and 67 deletions
|
@ -7,7 +7,6 @@ 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 { XPositionReference } from '../../Enums/XPositionReference';
|
||||
|
||||
/**
|
||||
|
@ -58,7 +57,7 @@ export function DeleteContainer(
|
|||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
const history = getCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[historyCurrentStep];
|
||||
const current = history[history.length - 1];
|
||||
|
||||
const mainContainerClone: IContainerModel = structuredClone(current.MainContainer);
|
||||
const container = findContainerById(mainContainerClone, containerId);
|
||||
|
@ -267,14 +266,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;
|
||||
|
|
|
@ -3,9 +3,10 @@ import { IContainerModel, ContainerModel } from '../../Interfaces/IContainerMode
|
|||
import { IHistoryState } from '../../Interfaces/IHistoryState';
|
||||
import { findContainerById } from '../../utils/itertools';
|
||||
import { getCurrentHistory } from './Editor';
|
||||
import { RecalculatePhysics } from './Behaviors/RigidBodyBehaviors';
|
||||
import { constraintBodyInsideUnallocatedWidth, 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
|
||||
|
@ -40,11 +41,7 @@ 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;
|
||||
}
|
||||
(container.properties as any)[key] = value;
|
||||
}
|
||||
|
||||
if (container.properties.isAnchor) {
|
||||
|
@ -96,39 +93,28 @@ export function OnPropertiesSubmit(
|
|||
}
|
||||
|
||||
// Assign container properties
|
||||
const form: HTMLFormElement = event.target as HTMLFormElement;
|
||||
for (const property in container.properties) {
|
||||
const input: HTMLInputElement | HTMLDivElement | null = (event.target as HTMLFormElement).querySelector(`#${property}`);
|
||||
const input: HTMLInputElement | HTMLDivElement | null = form.querySelector(`#${property}`);
|
||||
|
||||
if (input === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (input instanceof HTMLInputElement) {
|
||||
(container.properties as any)[property] = input.value;
|
||||
if (INPUT_TYPES[property] === 'number') {
|
||||
(container.properties as any)[property] = Number(input.value);
|
||||
}
|
||||
} else if (input instanceof HTMLDivElement) {
|
||||
const radiobutton: HTMLInputElement | null = input.querySelector(`input[name="${property}"]:checked`);
|
||||
submitHTMLInput(input, container, property, form);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (radiobutton === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(container.properties as any)[property] = radiobutton.value;
|
||||
if (INPUT_TYPES[property] === 'number') {
|
||||
(container.properties as any)[property] = Number(radiobutton.value);
|
||||
}
|
||||
if (input instanceof HTMLDivElement) {
|
||||
submitRadioButtons(input, container, property);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Assign cssproperties
|
||||
for (const styleProperty in container.properties.style) {
|
||||
const input: HTMLInputElement | null = (event.target as HTMLFormElement).querySelector(`#${styleProperty}`);
|
||||
if (input === null) {
|
||||
continue;
|
||||
}
|
||||
(container.properties.style as any)[styleProperty] = input.value;
|
||||
submitCSSForm(form, styleProperty, container);
|
||||
}
|
||||
|
||||
if (container.properties.isRigidBody) {
|
||||
|
@ -145,3 +131,67 @@ export function OnPropertiesSubmit(
|
|||
setHistory(history);
|
||||
setHistoryCurrentStep(history.length - 1);
|
||||
}
|
||||
|
||||
const submitHTMLInput = (
|
||||
input: HTMLInputElement,
|
||||
container: IContainerModel,
|
||||
property: string,
|
||||
form: HTMLFormElement
|
||||
): void => {
|
||||
if (INPUT_TYPES[property] !== 'number') {
|
||||
(container.properties as any)[property] = input.value;
|
||||
}
|
||||
|
||||
if (property === 'x') {
|
||||
// Hardcoded fix for XPositionReference
|
||||
const x = RestoreX(form, input);
|
||||
(container.properties as any)[property] = x;
|
||||
return;
|
||||
}
|
||||
|
||||
(container.properties as any)[property] = Number(input.value);
|
||||
};
|
||||
|
||||
const submitCSSForm = (form: HTMLFormElement, styleProperty: string, container: ContainerModel): void => {
|
||||
const input: HTMLInputElement | null = form.querySelector(`#${styleProperty}`);
|
||||
if (input === null) {
|
||||
return;
|
||||
}
|
||||
(container.properties.style as any)[styleProperty] = input.value;
|
||||
};
|
||||
|
||||
const RestoreX = (
|
||||
form: HTMLFormElement,
|
||||
input: HTMLInputElement
|
||||
): number => {
|
||||
const inputWidth: HTMLInputElement | null = form.querySelector('#width');
|
||||
const inputRadio: HTMLDivElement | null = form.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');
|
||||
}
|
||||
|
||||
return restoreX(Number(input.value), Number(inputWidth.value), Number(radiobutton.value));
|
||||
};
|
||||
|
||||
const submitRadioButtons = (
|
||||
div: HTMLDivElement,
|
||||
container: IContainerModel,
|
||||
property: string
|
||||
): void => {
|
||||
const radiobutton: HTMLInputElement | null = div.querySelector(`input[name="${property}"]:checked`);
|
||||
if (radiobutton === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (INPUT_TYPES[property] === 'number') {
|
||||
(container.properties as any)[property] = Number(radiobutton.value);
|
||||
return;
|
||||
}
|
||||
|
||||
(container.properties as any)[property] = radiobutton.value;
|
||||
};
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -68,8 +68,8 @@ describe.concurrent('Properties', () => {
|
|||
|
||||
expect(prop.id).toBe('stuff');
|
||||
expect(prop.parentId).toBe('parentId');
|
||||
expect(prop.x).toBe('2');
|
||||
expect(prop.y).toBe('2');
|
||||
expect(prop.x).toBe(2);
|
||||
expect(prop.y).toBe(2);
|
||||
rerender(<Properties
|
||||
properties={Object.assign({}, prop)}
|
||||
onChange={handleChange}
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue