import { IContainerModel } from '../../../Interfaces/IContainerModel'; import { ReversePairwise } from '../../../utils/itertools'; import { Flex } from './FlexBehaviors'; /** * Try to push the siblings * @param container * @returns */ export function PushContainers(container: IContainerModel): IContainerModel { if (container.parent === null) { return container; } if (container.parent.children.length <= 1) { return container; } const prevIndex = container.parent.children.length - 2; const prev: IContainerModel = container.parent.children[prevIndex]; const isOverlapping = prev.properties.x + prev.properties.width > container.properties.x; if (!isOverlapping) { return container; } // find hole let lastContainer: IContainerModel | null = null; let space: number = 0; while (space.toFixed(2) < container.properties.width.toFixed(2)) { // FIXME: possible infinite loop due to floating point // FIXME: A fix was applied using toFixed(2). // FIXME: A coverture check must be done to ensure that all scenarios are covered const it = ReversePairwise(container.parent.children.filter(child => child !== container)); for (const { cur, next } of it) { const hasSpaceBetween = next.properties.x + next.properties.width < cur.properties.x; if (hasSpaceBetween) { lastContainer = cur; space = cur.properties.x - (next.properties.x + next.properties.width); break; } } if (lastContainer === null) { // no space between break; } const indexLastContainer = container.parent.children.indexOf(lastContainer); for (let i = indexLastContainer; i <= container.parent.children.length - 2; i++) { const sibling = container.parent.children[i]; sibling.properties.x -= space; } } const hasNoSpaceBetween = lastContainer === null; if (hasNoSpaceBetween) { // test gap between the left of the parent and the first container space = container.parent.children[0].properties.x; if (space > 0) { for (let i = 0; i <= container.parent.children.length - 2; i++) { const sibling = container.parent.children[i]; sibling.properties.x -= space; } return container; } } Flex(container); return container; }