svg-layout-designer-react/src/Components/Editor/Behaviors/AnchorBehaviors.ts
Eric Nguyen 353f461f4b Merged PR 175: Implement drag drop
- [x] Implement drag drop to create an element at a specific index
- Add Swap behavrior
- Implement max contraints with simplex
~~- [ ] Implement drag drop to swap two container that flex~~

- Fixes tries number for simplex it can now go up to 2 * number of containers
- Fixes flex calling another flex behavior when not needed (remember that flex behavior is the only behavior that needs to communicate with siblings)
- Fix max width being ignored in input group
2022-09-05 07:56:45 +00:00

70 lines
2.3 KiB
TypeScript

/**
* @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
*/
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { ConstraintBodyInsideUnallocatedWidth } from './RigidBodyBehaviors';
/**
* Impose the container position to its siblings
* Apply the following modification to the overlapping rigid body container :
* @param container Container to impose its position
*/
export function ApplyAnchor(container: IContainerModel): IContainerModel {
if (container.parent === undefined ||
container.parent === null) {
return container;
}
const rigidBodies = container.parent.children.filter(
child => !child.properties.isAnchor
);
const overlappingContainers = GetOverlappingContainers(container, rigidBodies);
for (const overlappingContainer of overlappingContainers) {
ConstraintBodyInsideUnallocatedWidth(overlappingContainer);
}
return container;
}
/**
* Returns the overlapping containers with container
* @param container A container
* @param containers A list of containers
* @returns A list of overlapping containers
*/
export function GetOverlappingContainers(
container: IContainerModel,
containers: IContainerModel[]
): IContainerModel[] {
const min1 = container.properties.x;
const max1 = container.properties.x + container.properties.width;
const overlappingContainers: IContainerModel[] = [];
for (const other of containers) {
if (other === container) {
continue;
}
const min2 = other.properties.x;
const max2 = other.properties.x + other.properties.width;
const isOverlapping = Math.min(max1, max2) - Math.max(min1, min2) > 0;
if (!isOverlapping) {
continue;
}
overlappingContainers.push(other);
}
return overlappingContainers;
}