ERP-node/frontend/lib/utils/gridUtils.ts

199 lines
5.2 KiB
TypeScript
Raw Normal View History

2025-10-13 18:37:18 +09:00
import { Position, Size } from "@/types/screen";
import { GridSettings } from "@/types/screen-management";
2025-09-02 11:16:40 +09:00
// 🎯 10px 고정 격자 시스템
const GRID_SIZE = 10; // 고정값
2025-10-13 18:37:18 +09:00
export interface GridInfo {
gridSize: number; // 항상 10px
2025-10-13 18:37:18 +09:00
totalWidth: number;
totalHeight: number;
2025-09-02 11:16:40 +09:00
}
/**
* ()
2025-09-02 11:16:40 +09:00
*/
2025-10-13 18:37:18 +09:00
export function calculateGridInfo(
containerWidth: number,
containerHeight: number,
_gridSettings?: GridSettings, // 호환성 유지용 (사용 안 함)
2025-10-13 18:37:18 +09:00
): GridInfo {
return {
gridSize: GRID_SIZE,
2025-10-13 18:37:18 +09:00
totalWidth: containerWidth,
totalHeight: containerHeight,
};
2025-09-02 11:16:40 +09:00
}
/**
* 10px
2025-09-02 11:16:40 +09:00
*/
export function snapToGrid(position: Position, _gridInfo: GridInfo, gridSettings: GridSettings): Position {
2025-10-13 18:37:18 +09:00
if (!gridSettings.snapToGrid) {
return position;
2025-09-02 11:16:40 +09:00
}
return {
x: Math.round(position.x / GRID_SIZE) * GRID_SIZE,
y: Math.round(position.y / GRID_SIZE) * GRID_SIZE,
2025-10-13 18:37:18 +09:00
z: position.z,
2025-09-02 11:16:40 +09:00
};
}
/**
* 10px
2025-09-02 11:16:40 +09:00
*/
export function snapSizeToGrid(size: Size, _gridInfo: GridInfo, gridSettings: GridSettings): Size {
2025-10-13 18:37:18 +09:00
if (!gridSettings.snapToGrid) {
return size;
}
2025-09-02 11:16:40 +09:00
2025-09-03 11:32:09 +09:00
return {
width: Math.max(GRID_SIZE, Math.round(size.width / GRID_SIZE) * GRID_SIZE),
height: Math.max(GRID_SIZE, Math.round(size.height / GRID_SIZE) * GRID_SIZE),
2025-09-03 11:32:09 +09:00
};
}
/**
* (10px )
2025-09-02 11:16:40 +09:00
*/
2025-10-13 18:37:18 +09:00
export function generateGridLines(
containerWidth: number,
containerHeight: number,
_gridSettings?: GridSettings,
2025-10-13 18:37:18 +09:00
): {
verticalLines: number[];
horizontalLines: number[];
} {
const verticalLines: number[] = [];
for (let x = 0; x <= containerWidth; x += GRID_SIZE) {
verticalLines.push(x);
2025-10-13 18:37:18 +09:00
}
const horizontalLines: number[] = [];
for (let y = 0; y <= containerHeight; y += GRID_SIZE) {
2025-10-13 18:37:18 +09:00
horizontalLines.push(y);
}
2025-09-02 11:16:40 +09:00
return {
2025-10-13 18:37:18 +09:00
verticalLines,
horizontalLines,
2025-09-02 11:16:40 +09:00
};
}
/**
2025-10-13 18:37:18 +09:00
*
2025-09-02 11:16:40 +09:00
*/
2025-10-13 18:37:18 +09:00
export function isOnGridBoundary(
position: Position,
size: Size,
gridInfo: GridInfo,
gridSettings: GridSettings,
tolerance: number = 5,
2025-09-02 11:16:40 +09:00
): boolean {
2025-10-13 18:37:18 +09:00
const snappedPos = snapToGrid(position, gridInfo, gridSettings);
const snappedSize = snapSizeToGrid(size, gridInfo, gridSettings);
const positionMatch =
Math.abs(position.x - snappedPos.x) <= tolerance && Math.abs(position.y - snappedPos.y) <= tolerance;
const sizeMatch =
Math.abs(size.width - snappedSize.width) <= tolerance && Math.abs(size.height - snappedSize.height) <= tolerance;
return positionMatch && sizeMatch;
2025-09-03 11:32:09 +09:00
}
/**
2025-10-13 18:37:18 +09:00
*
2025-09-03 11:32:09 +09:00
*/
2025-10-13 18:37:18 +09:00
export function alignGroupChildrenToGrid(
children: any[],
groupPosition: Position,
gridInfo: GridInfo,
gridSettings: GridSettings,
): any[] {
if (!gridSettings.snapToGrid || children.length === 0) return children;
2025-09-03 11:32:09 +09:00
return children.map((child) => {
2025-10-13 18:37:18 +09:00
const padding = 16;
// 10px 단위로 스냅
const snappedX = Math.max(padding, Math.round((child.position.x - padding) / GRID_SIZE) * GRID_SIZE + padding);
const snappedY = Math.max(padding, Math.round((child.position.y - padding) / GRID_SIZE) * GRID_SIZE + padding);
const snappedWidth = Math.max(GRID_SIZE, Math.round(child.size.width / GRID_SIZE) * GRID_SIZE);
const snappedHeight = Math.max(GRID_SIZE, Math.round(child.size.height / GRID_SIZE) * GRID_SIZE);
return {
2025-10-13 18:37:18 +09:00
...child,
position: {
x: snappedX,
y: snappedY,
2025-10-13 18:37:18 +09:00
z: child.position.z || 1,
},
size: {
width: snappedWidth,
height: snappedHeight,
},
};
});
}
/**
*
*/
export function calculateOptimalGroupSize(
children: Array<{ position: Position; size: Size }>,
_gridInfo?: GridInfo,
_gridSettings?: GridSettings,
2025-10-13 18:37:18 +09:00
): Size {
if (children.length === 0) {
return { width: GRID_SIZE * 20, height: GRID_SIZE * 10 };
2025-10-13 18:37:18 +09:00
}
const bounds = children.reduce(
(acc, child) => ({
minX: Math.min(acc.minX, child.position.x),
minY: Math.min(acc.minY, child.position.y),
maxX: Math.max(acc.maxX, child.position.x + child.size.width),
maxY: Math.max(acc.maxY, child.position.y + child.size.height),
}),
{ minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity },
);
const contentWidth = bounds.maxX - bounds.minX;
const contentHeight = bounds.maxY - bounds.minY;
const padding = 16;
2025-10-13 18:37:18 +09:00
return {
2025-10-13 18:37:18 +09:00
width: contentWidth + padding * 2,
height: contentHeight + padding * 2,
};
2025-10-13 18:37:18 +09:00
}
/**
*
*/
export function normalizeGroupChildPositions(children: any[], _gridSettings?: GridSettings): any[] {
if (children.length === 0) return children;
2025-10-13 18:37:18 +09:00
const minX = Math.min(...children.map((child) => child.position.x));
const minY = Math.min(...children.map((child) => child.position.y));
const padding = 16;
return children.map((child) => ({
2025-10-13 18:37:18 +09:00
...child,
position: {
x: child.position.x - minX + padding,
y: child.position.y - minY + padding,
2025-10-13 18:37:18 +09:00
z: child.position.z || 1,
},
}));
2025-09-03 11:32:09 +09:00
}
// 🗑️ 제거된 함수들 (더 이상 필요 없음)
// - calculateWidthFromColumns
// - updateSizeFromGridColumns
// - adjustGridColumnsFromSize
// - calculateColumnsFromWidth