Implémenter l'orientation verticale Modifier l'effet de append Implementer RigidBody Implementer Flex et simplex Implémenter Push Implémenter Swap Implement MinMaxHeight without behaviors Fix Margin for Height Implement PositionReference Fix dimension vertical position inside children Add orientation change in form Implement sortChildren Implement Anchor Fix warning message on overlapping Fix minimap when root container is vertical #7287 #7288 #7289 #7290 #7291 #7292 #7294 #7295 #7296 #7297 #7298 #7299 #7300 #7301 #7302
139 lines
4.3 KiB
TypeScript
139 lines
4.3 KiB
TypeScript
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
|
import { Orientation } from '../../../Interfaces/Orientation';
|
|
import { ReversePairwise } from '../../../utils/itertools';
|
|
import { Flex } from './FlexBehaviors';
|
|
|
|
/**
|
|
* Try to push the siblings
|
|
* @param container
|
|
* @returns
|
|
*/
|
|
export function ApplyPush(container: IContainerModel, parent: IContainerModel): IContainerModel {
|
|
if (parent.children.length <= 1) {
|
|
return container;
|
|
}
|
|
|
|
const children = parent.children;
|
|
const isHorizontal = parent.properties.orientation === Orientation.Horizontal;
|
|
|
|
if (isHorizontal) {
|
|
PushContainersHorizontally(container, children);
|
|
} else {
|
|
PushContainersVertically(container, children);
|
|
}
|
|
|
|
Flex(container, parent);
|
|
return container;
|
|
}
|
|
|
|
export function PushContainersHorizontally(container: IContainerModel, children: IContainerModel[]): IContainerModel {
|
|
const prevIndex = children.length - 2;
|
|
const prev: IContainerModel = 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<IContainerModel>(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 = children.indexOf(lastContainer);
|
|
for (let i = indexLastContainer; i <= children.length - 2; i++) {
|
|
const sibling = 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 = children[0].properties.x;
|
|
if (space > 0) {
|
|
for (let i = 0; i <= children.length - 2; i++) {
|
|
const sibling = children[i];
|
|
sibling.properties.x -= space;
|
|
}
|
|
return container;
|
|
}
|
|
}
|
|
|
|
return container;
|
|
}
|
|
|
|
export function PushContainersVertically(container: IContainerModel, children: IContainerModel[]): IContainerModel {
|
|
const prevIndex = children.length - 2;
|
|
const prev: IContainerModel = children[prevIndex];
|
|
const isOverlapping = prev.properties.y + prev.properties.height > container.properties.y;
|
|
if (!isOverlapping) {
|
|
return container;
|
|
}
|
|
|
|
// find hole
|
|
let lastContainer: IContainerModel | null = null;
|
|
let space: number = 0;
|
|
|
|
while (space.toFixed(2) < container.properties.height.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<IContainerModel>(children.filter(child => child !== container));
|
|
|
|
for (const { cur, next } of it) {
|
|
const hasSpaceBetween = next.properties.y + next.properties.height < cur.properties.y;
|
|
if (hasSpaceBetween) {
|
|
lastContainer = cur;
|
|
space = cur.properties.y - (next.properties.y + next.properties.height);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (lastContainer === null) {
|
|
// no space between
|
|
break;
|
|
}
|
|
|
|
const indexLastContainer = children.indexOf(lastContainer);
|
|
for (let i = indexLastContainer; i <= children.length - 2; i++) {
|
|
const sibling = children[i];
|
|
sibling.properties.y -= space;
|
|
}
|
|
}
|
|
|
|
const hasNoSpaceBetween = lastContainer === null;
|
|
if (hasNoSpaceBetween) {
|
|
// test gap between the left of the parent and the first container
|
|
space = children[0].properties.y;
|
|
if (space > 0) {
|
|
for (let i = 0; i <= children.length - 2; i++) {
|
|
const sibling = children[i];
|
|
sibling.properties.y -= space;
|
|
}
|
|
return container;
|
|
}
|
|
}
|
|
|
|
return container;
|
|
}
|