From 0b41f7ac2cba632557306c9fa7729e5388081276 Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Fri, 12 Aug 2022 14:15:40 +0200 Subject: [PATCH] Implement isAnchor basics properties + fix IsRigidbody --- src/Components/App/MenuActions.ts | 3 +- .../Editor/Behaviors/AnchorBehaviors.ts | 23 +++++++++++++++ .../{ => Behaviors}/RigidBodyBehaviors.ts | 29 ++++++++++++------- src/Components/Editor/ContainerOperations.ts | 26 ++++++++++------- src/Components/Editor/PropertiesOperations.ts | 1 + .../ElementsSidebar/ElementsSidebar.test.tsx | 21 +++++++++----- src/Components/Properties/Properties.test.tsx | 3 +- .../Properties/PropertiesInputTypes.tsx | 3 +- src/Interfaces/IProperties.ts | 10 +++++++ src/utils/default.ts | 1 + 10 files changed, 89 insertions(+), 31 deletions(-) create mode 100644 src/Components/Editor/Behaviors/AnchorBehaviors.ts rename src/Components/Editor/{ => Behaviors}/RigidBodyBehaviors.ts (88%) diff --git a/src/Components/App/MenuActions.ts b/src/Components/App/MenuActions.ts index c849ca8..c144acc 100644 --- a/src/Components/App/MenuActions.ts +++ b/src/Components/App/MenuActions.ts @@ -2,7 +2,7 @@ import { Dispatch, SetStateAction } from 'react'; import { IConfiguration } from '../../Interfaces/IConfiguration'; import { ContainerModel } from '../../Interfaces/IContainerModel'; import { fetchConfiguration } from '../API/api'; -import { IEditorState } from "../../Interfaces/IEditorState"; +import { IEditorState } from '../../Interfaces/IEditorState'; import { LoadState } from './Load'; export function NewEditor( @@ -23,6 +23,7 @@ export function NewEditor( width: configuration.MainContainer.Width, height: configuration.MainContainer.Height, isRigidBody: false, + isAnchor: false, fillOpacity: 0, stroke: 'black' } diff --git a/src/Components/Editor/Behaviors/AnchorBehaviors.ts b/src/Components/Editor/Behaviors/AnchorBehaviors.ts new file mode 100644 index 0000000..a5e02f7 --- /dev/null +++ b/src/Components/Editor/Behaviors/AnchorBehaviors.ts @@ -0,0 +1,23 @@ +/** + * @module AnchorBehavior + * + * An anchor is a container that takes physical priority in the representation : + * - It cannot be moved by other rigid siblings container + * - It cannot be resized by any other siblings container + * - It cannot overlap any other siblings rigid container : + * - overlapping container are shifted to the nearest available space/width + * - or resized when there is no available space left other than theirs + * - or lose their rigid body properties when there is no available space left) + * Meaning that: + * - Moving an anchor container will resize the width of an overlapping container + * or make them lose their property as a rigid body + */ + +/** + * Impose the container position + * Apply the following modification to the overlapping rigid body container : + * + */ +export function ImposePosition(){ + +} \ No newline at end of file diff --git a/src/Components/Editor/RigidBodyBehaviors.ts b/src/Components/Editor/Behaviors/RigidBodyBehaviors.ts similarity index 88% rename from src/Components/Editor/RigidBodyBehaviors.ts rename to src/Components/Editor/Behaviors/RigidBodyBehaviors.ts index 116fbc4..b250ed2 100644 --- a/src/Components/Editor/RigidBodyBehaviors.ts +++ b/src/Components/Editor/Behaviors/RigidBodyBehaviors.ts @@ -1,5 +1,13 @@ -import { IContainerModel } from '../../Interfaces/IContainerModel'; -import { ISizePointer } from '../../Interfaces/ISizePointer'; +/** + * @module RigidBodyBehaviors + * Apply the following contraints to the `container` : + * - The container must be kept inside its parent + * - The container must find an unallocated space within the parent + * If the contraints fails, an error message will be returned + */ + +import { IContainerModel } from '../../../Interfaces/IContainerModel'; +import { ISizePointer } from '../../../Interfaces/ISizePointer'; /** * "Transform the container into a rigid body" @@ -179,17 +187,18 @@ function getAvailableWidths( const width = Number(container.properties.width); let unallocatedSpaces: ISizePointer[] = [{ x, width }]; - // We will only uses containers that also have the rigid bodies - // as out-of-bound or enormouse containers should be ignored - const rigidBodies = container.children.filter( - (child) => child.properties.isRigidBody + // We will only uses containers that also are rigid or are anchors + const solidBodies = container.children.filter( + (child) => child.properties.isRigidBody || child.properties.isAnchor ); - for (const child of rigidBodies) { + for (const child of solidBodies) { // Ignore the exception if (child === exception) { continue; } + const childX = child.properties.x; + const childWidth = Number(child.properties.width); // get the space of the child that is inside the parent let newUnallocatedSpace: ISizePointer[] = []; @@ -202,8 +211,8 @@ function getAvailableWidths( const newUnallocatedWidths = getAvailableWidthsTwoLines( unallocatedSpace.x, unallocatedSpace.x + unallocatedSpace.width, - child.properties.x, - child.properties.x + Number(child.properties.width) + childX, + childX + childWidth ); // Concat the new list of SizePointer pointing to availables spaces @@ -262,7 +271,7 @@ function getAvailableWidthsTwoLines( width: min2 - min1 }, { - x: min2, + x: max2, width: max1 - max2 } ]; diff --git a/src/Components/Editor/ContainerOperations.ts b/src/Components/Editor/ContainerOperations.ts index 40391c5..63d90a0 100644 --- a/src/Components/Editor/ContainerOperations.ts +++ b/src/Components/Editor/ContainerOperations.ts @@ -4,6 +4,7 @@ import { IConfiguration } from '../../Interfaces/IConfiguration'; import { ContainerModel, IContainerModel } from '../../Interfaces/IContainerModel'; import { findContainerById } from '../../utils/itertools'; import { getCurrentHistory } from './Editor'; +import IProperties from '../../Interfaces/IProperties'; /** * Select a container @@ -203,20 +204,23 @@ export function AddContainer( } } + const defaultProperties: IProperties = { + id: `${type}-${count}`, + parentId: parentClone.properties.id, + x, + y: 0, + width: properties.Width, + height: parentClone.properties.height, + isRigidBody: false, + isAnchor: false, + XPositionReference: properties.XPositionReference, + ...properties.Style + }; + // Create the container const newContainer = new ContainerModel( parentClone, - { - id: `${type}-${count}`, - parentId: parentClone.properties.id, - x, - y: 0, - width: properties?.Width, - height: parentClone.properties.height, - isRigidBody: false, - XPositionReference: properties.XPositionReference, - ...properties.Style - }, + defaultProperties, [], { type diff --git a/src/Components/Editor/PropertiesOperations.ts b/src/Components/Editor/PropertiesOperations.ts index bdcc03d..e271776 100644 --- a/src/Components/Editor/PropertiesOperations.ts +++ b/src/Components/Editor/PropertiesOperations.ts @@ -4,6 +4,7 @@ import { IHistoryState } from '../../Interfaces/IHistoryState'; import IProperties from '../../Interfaces/IProperties'; import { findContainerById } from '../../utils/itertools'; import { getCurrentHistory } from './Editor'; +import { RecalculatePhysics } from './Behaviors/RigidBodyBehaviors'; import { INPUT_TYPES } from '../Properties/PropertiesInputTypes'; /** diff --git a/src/Components/ElementsSidebar/ElementsSidebar.test.tsx b/src/Components/ElementsSidebar/ElementsSidebar.test.tsx index f1776c0..8d34480 100644 --- a/src/Components/ElementsSidebar/ElementsSidebar.test.tsx +++ b/src/Components/ElementsSidebar/ElementsSidebar.test.tsx @@ -17,7 +17,8 @@ describe.concurrent('Elements sidebar', () => { y: 0, width: 2000, height: 100, - isRigidBody: false + isRigidBody: false, + isAnchor: false }, userData: {} }} @@ -47,7 +48,8 @@ describe.concurrent('Elements sidebar', () => { y: 0, width: 2000, height: 100, - isRigidBody: false + isRigidBody: false, + isAnchor: false }, userData: {} }; @@ -103,7 +105,8 @@ describe.concurrent('Elements sidebar', () => { y: 0, width: 2000, height: 100, - isRigidBody: false + isRigidBody: false, + isAnchor: false }, userData: {} }; @@ -119,7 +122,8 @@ describe.concurrent('Elements sidebar', () => { y: 0, width: 0, height: 0, - isRigidBody: false + isRigidBody: false, + isAnchor: false }, userData: {} } @@ -136,7 +140,8 @@ describe.concurrent('Elements sidebar', () => { y: 0, width: 0, height: 0, - isRigidBody: false + isRigidBody: false, + isAnchor: false }, userData: {} } @@ -173,7 +178,8 @@ describe.concurrent('Elements sidebar', () => { y: 0, width: 2000, height: 100, - isRigidBody: false + isRigidBody: false, + isAnchor: false }, userData: {} }; @@ -188,7 +194,8 @@ describe.concurrent('Elements sidebar', () => { y: 0, width: 0, height: 0, - isRigidBody: false + isRigidBody: false, + isAnchor: false }, userData: {} }; diff --git a/src/Components/Properties/Properties.test.tsx b/src/Components/Properties/Properties.test.tsx index 2afc364..9fbef37 100644 --- a/src/Components/Properties/Properties.test.tsx +++ b/src/Components/Properties/Properties.test.tsx @@ -23,7 +23,8 @@ describe.concurrent('Properties', () => { parentId: 'parentId', x: 1, y: 1, - isRigidBody: false + isRigidBody: false, + isAnchor: false }; const handleChange = vi.fn((key, value) => { diff --git a/src/Components/Properties/PropertiesInputTypes.tsx b/src/Components/Properties/PropertiesInputTypes.tsx index c62a8fd..d91ddbc 100644 --- a/src/Components/Properties/PropertiesInputTypes.tsx +++ b/src/Components/Properties/PropertiesInputTypes.tsx @@ -3,5 +3,6 @@ export const INPUT_TYPES: Record = { y: 'number', width: 'number', height: 'number', - isRigidBody: 'checkbox' + isRigidBody: 'checkbox', + isAnchor: 'checkbox' }; diff --git a/src/Interfaces/IProperties.ts b/src/Interfaces/IProperties.ts index 4996ce5..ef2db7e 100644 --- a/src/Interfaces/IProperties.ts +++ b/src/Interfaces/IProperties.ts @@ -1,11 +1,21 @@ import * as React from 'react'; import { XPositionReference } from '../Enums/XPositionReference'; +/** + * Properties of a container + * @property id id of the container + * @property parentId id of the parent container + * @property x horizontal offset of the container + * @property y vertical offset of the container + * @property isRigidBody if true apply rigid body behaviors + * @property isAnchor if true apply anchor behaviors + */ export default interface IProperties extends React.CSSProperties { id: string parentId: string | null x: number y: number isRigidBody: boolean + isAnchor: boolean XPositionReference?: XPositionReference } diff --git a/src/utils/default.ts b/src/utils/default.ts index 785a840..2bd22dc 100644 --- a/src/utils/default.ts +++ b/src/utils/default.ts @@ -33,6 +33,7 @@ export const DEFAULT_MAINCONTAINER_PROPS: IProperties = { width: DEFAULT_CONFIG.MainContainer.Width, height: DEFAULT_CONFIG.MainContainer.Height, isRigidBody: false, + isAnchor: false, fillOpacity: 0, stroke: 'black' };