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)
70 lines
2.4 KiB
TypeScript
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;
|
|
}
|