mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-08-14 12:50:37 +03:00
M: Improve positioning for new nodes
This commit is contained in:
parent
c17ed15905
commit
65eacba03c
|
@ -34,8 +34,10 @@ export class LayoutManager {
|
||||||
newOperationPosition(data: ICreateSchemaDTO | ICreateSynthesisDTO | IImportSchemaDTO): Rectangle2D {
|
newOperationPosition(data: ICreateSchemaDTO | ICreateSynthesisDTO | IImportSchemaDTO): Rectangle2D {
|
||||||
const result = { ...data.position };
|
const result = { ...data.position };
|
||||||
const parentNode = this.layout.find(pos => pos.nodeID === `b${data.item_data.parent}`) ?? null;
|
const parentNode = this.layout.find(pos => pos.nodeID === `b${data.item_data.parent}`) ?? null;
|
||||||
|
const parentID = parentNode ? data.item_data.parent : null;
|
||||||
const operations = this.layout.filter(pos => pos.nodeID.startsWith('o'));
|
const operations = this.layout.filter(pos => pos.nodeID.startsWith('o'));
|
||||||
if ('arguments' in data && data.arguments.length !== 0) {
|
const hasArguments = 'arguments' in data && data.arguments.length !== 0;
|
||||||
|
if (hasArguments) {
|
||||||
const pos = calculatePositionFromArgs(
|
const pos = calculatePositionFromArgs(
|
||||||
operations.filter(node => data.arguments.includes(Number(node.nodeID.slice(1))))
|
operations.filter(node => data.arguments.includes(Number(node.nodeID.slice(1))))
|
||||||
);
|
);
|
||||||
|
@ -50,6 +52,16 @@ export class LayoutManager {
|
||||||
result.y = pos.y;
|
result.y = pos.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const siblingBlocks = this.oss.blocks.filter(block => block.parent === parentID).map(block => block.nodeID);
|
||||||
|
preventOverlap(
|
||||||
|
result,
|
||||||
|
this.layout.filter(node => siblingBlocks.includes(node.nodeID)),
|
||||||
|
{
|
||||||
|
moveX: !hasArguments,
|
||||||
|
moveY: hasArguments
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
preventOverlap(result, operations);
|
preventOverlap(result, operations);
|
||||||
this.extendParentBounds(parentNode, result);
|
this.extendParentBounds(parentNode, result);
|
||||||
|
|
||||||
|
@ -65,6 +77,7 @@ export class LayoutManager {
|
||||||
.map(id => this.layout.find(operation => operation.nodeID === `o${id}`))
|
.map(id => this.layout.find(operation => operation.nodeID === `o${id}`))
|
||||||
.filter(node => !!node);
|
.filter(node => !!node);
|
||||||
const parentNode = this.layout.find(pos => pos.nodeID === `b${data.item_data.parent}`) ?? null;
|
const parentNode = this.layout.find(pos => pos.nodeID === `b${data.item_data.parent}`) ?? null;
|
||||||
|
const parentID = parentNode ? data.item_data.parent : null;
|
||||||
|
|
||||||
let result: Rectangle2D = { ...data.position };
|
let result: Rectangle2D = { ...data.position };
|
||||||
|
|
||||||
|
@ -82,25 +95,11 @@ export class LayoutManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block_nodes.length === 0 && operation_nodes.length === 0) {
|
if (block_nodes.length === 0 && operation_nodes.length === 0) {
|
||||||
if (parentNode) {
|
const siblings = this.oss.blocks.filter(block => block.parent === parentID).map(block => block.nodeID);
|
||||||
const siblings = this.oss.blocks
|
preventOverlap(
|
||||||
.filter(block => block.parent === data.item_data.parent)
|
result,
|
||||||
.map(block => block.nodeID);
|
this.layout.filter(node => siblings.includes(node.nodeID))
|
||||||
if (siblings.length > 0) {
|
);
|
||||||
preventOverlap(
|
|
||||||
result,
|
|
||||||
this.layout.filter(node => siblings.includes(node.nodeID))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const rootBlocks = this.oss.blocks.filter(block => block.parent === null).map(block => block.nodeID);
|
|
||||||
if (rootBlocks.length > 0) {
|
|
||||||
preventOverlap(
|
|
||||||
result,
|
|
||||||
this.layout.filter(node => rootBlocks.includes(node.nodeID))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.extendParentBounds(parentNode, result);
|
this.extendParentBounds(parentNode, result);
|
||||||
|
@ -203,15 +202,26 @@ function rectanglesOverlap(a: Rectangle2D, b: Rectangle2D): boolean {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function preventOverlap(target: Rectangle2D, fixedRectangles: Rectangle2D[]) {
|
function preventOverlap(
|
||||||
|
target: Rectangle2D,
|
||||||
|
fixedRectangles: Rectangle2D[],
|
||||||
|
options: { moveX?: boolean; moveY?: boolean } = { moveX: true, moveY: true }
|
||||||
|
) {
|
||||||
|
if ((!options.moveX && !options.moveY) || fixedRectangles.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let hasOverlap: boolean;
|
let hasOverlap: boolean;
|
||||||
do {
|
do {
|
||||||
hasOverlap = false;
|
hasOverlap = false;
|
||||||
for (const fixed of fixedRectangles) {
|
for (const fixed of fixedRectangles) {
|
||||||
if (rectanglesOverlap(target, fixed)) {
|
if (rectanglesOverlap(target, fixed)) {
|
||||||
hasOverlap = true;
|
hasOverlap = true;
|
||||||
target.x += MIN_DISTANCE;
|
if (options.moveX) {
|
||||||
target.y += MIN_DISTANCE;
|
target.x += MIN_DISTANCE;
|
||||||
|
}
|
||||||
|
if (options.moveY) {
|
||||||
|
target.y += MIN_DISTANCE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user