svg-layout-designer-react/src/Components/Editor/Behaviors/AnchorBehaviors.ts
Eric Nguyen 8b8d88f885 Merged PR 162: Implement symbols and other stuff (see desc)
Implement symbols
- Add, Remove, Select Container
- Form
- Link with container
- Symbol behavior application to container (move to x with xpositionreference)

Important changes
- Remove SelectedContainer from HistoryState, meaning that it will be slower for each load but will be faster for each operations* (SetHistory, SelectContainer, DeleteContainer, SymbolOperations)
- ElementsSidebar now opens with isSidebarOpen meaning that both sidebar will open on toggle
- Moved camelize, transformX, restoreX to different modules (stringtools.ts, svg.ts)
2022-08-22 13:58:32 +00:00

70 lines
2.4 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.isRigidBody && !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
*/
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;
}