B: Fix inserting operation in empty OSS

This commit is contained in:
Ivan 2024-09-19 16:26:49 +03:00
parent 9e075dc67d
commit ccf1818e20
2 changed files with 62 additions and 37 deletions

View File

@ -1,7 +1,10 @@
/** /**
* Module: API for miscellaneous frontend model types. Future targets for refactoring aimed at extracting modules. * Module: API for miscellaneous frontend model types. Future targets for refactoring aimed at extracting modules.
*/ */
import { DependencyMode, GraphSizing } from './miscellaneous'; import { PARAMETER } from '@/utils/constants';
import { DependencyMode, GraphSizing, Position2D } from './miscellaneous';
import { IOperationPosition, IOperationSchema, OperationID, OperationType } from './oss';
import { IConstituenta, IRSForm } from './rsform'; import { IConstituenta, IRSForm } from './rsform';
/** /**
@ -47,3 +50,53 @@ export function applyNodeSizing(target: IConstituenta, sizing: GraphSizing): num
return target.spawner ? 1 : 2; return target.spawner ? 1 : 2;
} }
} }
/**
* Calculate insert position for a new {@link IOperation}
*/
export function calculateInsertPosition(
oss: IOperationSchema,
operationType: OperationType,
argumentsOps: OperationID[],
positions: IOperationPosition[],
defaultPosition: Position2D
): Position2D {
const result = defaultPosition;
if (positions.length === 0) {
return result;
}
if (operationType === OperationType.INPUT) {
let inputsNodes = positions.filter(pos =>
oss.items.find(operation => operation.operation_type === OperationType.INPUT && operation.id === pos.id)
);
if (inputsNodes.length > 0) {
inputsNodes = positions;
}
const maxX = Math.max(...inputsNodes.map(node => node.position_x));
const minY = Math.min(...inputsNodes.map(node => node.position_y));
result.x = maxX + PARAMETER.ossDistanceX;
result.y = minY;
} else {
const argNodes = positions.filter(pos => argumentsOps.includes(pos.id));
const maxY = Math.max(...argNodes.map(node => node.position_y));
const minX = Math.min(...argNodes.map(node => node.position_x));
const maxX = Math.max(...argNodes.map(node => node.position_x));
result.x = Math.ceil((maxX + minX) / 2 / PARAMETER.ossGridSize) * PARAMETER.ossGridSize;
result.y = maxY + PARAMETER.ossDistanceY;
}
let flagIntersect = false;
do {
flagIntersect = positions.some(
position =>
Math.abs(position.position_x - result.x) < PARAMETER.ossMinDistance &&
Math.abs(position.position_y - result.y) < PARAMETER.ossMinDistance
);
if (flagIntersect) {
result.x += PARAMETER.ossMinDistance;
result.y += PARAMETER.ossMinDistance;
}
} while (flagIntersect);
return result;
}

View File

@ -19,6 +19,7 @@ import DlgEditEditors from '@/dialogs/DlgEditEditors';
import DlgEditOperation from '@/dialogs/DlgEditOperation'; import DlgEditOperation from '@/dialogs/DlgEditOperation';
import { AccessPolicy, ILibraryItemEditor, LibraryItemID } from '@/models/library'; import { AccessPolicy, ILibraryItemEditor, LibraryItemID } from '@/models/library';
import { Position2D } from '@/models/miscellaneous'; import { Position2D } from '@/models/miscellaneous';
import { calculateInsertPosition } from '@/models/miscellaneousAPI';
import { import {
IOperationCreateData, IOperationCreateData,
IOperationDeleteData, IOperationDeleteData,
@ -234,42 +235,13 @@ export const OssEditState = ({ selected, setSelected, children }: OssEditStatePr
const handleCreateOperation = useCallback( const handleCreateOperation = useCallback(
(data: IOperationCreateData) => { (data: IOperationCreateData) => {
const target = insertPosition; const target = calculateInsertPosition(
if (data.item_data.operation_type === OperationType.INPUT) { model.schema!,
let inputsNodes = positions.filter(pos => data.item_data.operation_type,
model.schema!.items.find( data.arguments!,
operation => operation.operation_type === OperationType.INPUT && operation.id === pos.id positions,
) insertPosition
); );
if (inputsNodes.length > 0) {
inputsNodes = positions;
}
const maxX = Math.max(...inputsNodes.map(node => node.position_x));
const minY = Math.min(...inputsNodes.map(node => node.position_y));
target.x = maxX + PARAMETER.ossDistanceX;
target.y = minY;
} else {
const argNodes = positions.filter(pos => data.arguments!.includes(pos.id));
const maxY = Math.max(...argNodes.map(node => node.position_y));
const minX = Math.min(...argNodes.map(node => node.position_x));
const maxX = Math.max(...argNodes.map(node => node.position_x));
target.x = Math.ceil((maxX + minX) / 2 / PARAMETER.ossGridSize) * PARAMETER.ossGridSize;
target.y = maxY + PARAMETER.ossDistanceY;
}
let flagIntersect = false;
do {
flagIntersect = positions.some(
position =>
Math.abs(position.position_x - target.x) < PARAMETER.ossMinDistance &&
Math.abs(position.position_y - target.y) < PARAMETER.ossMinDistance
);
if (flagIntersect) {
target.x += PARAMETER.ossMinDistance;
target.y += PARAMETER.ossMinDistance;
}
} while (flagIntersect);
data.positions = positions; data.positions = positions;
data.item_data.position_x = target.x; data.item_data.position_x = target.x;
data.item_data.position_y = target.y; data.item_data.position_y = target.y;