From ccf1818e20e0288ee4b35f35711830e5fc08c4a9 Mon Sep 17 00:00:00 2001 From: Ivan <8611739+IRBorisov@users.noreply.github.com> Date: Thu, 19 Sep 2024 16:26:49 +0300 Subject: [PATCH] B: Fix inserting operation in empty OSS --- .../frontend/src/models/miscellaneousAPI.ts | 55 ++++++++++++++++++- .../src/pages/OssPage/OssEditContext.tsx | 44 +++------------ 2 files changed, 62 insertions(+), 37 deletions(-) diff --git a/rsconcept/frontend/src/models/miscellaneousAPI.ts b/rsconcept/frontend/src/models/miscellaneousAPI.ts index 6d077e90..205f0217 100644 --- a/rsconcept/frontend/src/models/miscellaneousAPI.ts +++ b/rsconcept/frontend/src/models/miscellaneousAPI.ts @@ -1,7 +1,10 @@ /** * 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'; /** @@ -47,3 +50,53 @@ export function applyNodeSizing(target: IConstituenta, sizing: GraphSizing): num 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; +} diff --git a/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx b/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx index a1e96f72..4a24364e 100644 --- a/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx +++ b/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx @@ -19,6 +19,7 @@ import DlgEditEditors from '@/dialogs/DlgEditEditors'; import DlgEditOperation from '@/dialogs/DlgEditOperation'; import { AccessPolicy, ILibraryItemEditor, LibraryItemID } from '@/models/library'; import { Position2D } from '@/models/miscellaneous'; +import { calculateInsertPosition } from '@/models/miscellaneousAPI'; import { IOperationCreateData, IOperationDeleteData, @@ -234,42 +235,13 @@ export const OssEditState = ({ selected, setSelected, children }: OssEditStatePr const handleCreateOperation = useCallback( (data: IOperationCreateData) => { - const target = insertPosition; - if (data.item_data.operation_type === OperationType.INPUT) { - let inputsNodes = positions.filter(pos => - model.schema!.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)); - 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); - + const target = calculateInsertPosition( + model.schema!, + data.item_data.operation_type, + data.arguments!, + positions, + insertPosition + ); data.positions = positions; data.item_data.position_x = target.x; data.item_data.position_y = target.y;