From cf8eeedeb99b5361fbcfa9af4f8cbf8460ebf708 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?=
<43837214+Minsiki@users.noreply.github.com>
Date: Tue, 7 Jan 2025 11:09:22 +0900
Subject: [PATCH] =?UTF-8?q?-=20=EB=AA=A8=EB=93=88=20=EA=B0=80=EB=A1=9C.?=
=?UTF-8?q?=EC=84=B8=EB=A1=9C=20=EC=A0=95=EB=A0=AC=20=EC=B6=94=EA=B0=80=20?=
=?UTF-8?q?-=20=EB=AA=A8=EB=93=88=20=EC=9D=BC=EA=B4=84=20=EC=82=AD?=
=?UTF-8?q?=EC=A0=9C=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../floor-plan/modal/module/PanelEdit.jsx | 10 +-
src/hooks/module/useModule.js | 279 ++++++++++++++----
src/hooks/useContextMenu.js | 40 +--
3 files changed, 251 insertions(+), 78 deletions(-)
diff --git a/src/components/floor-plan/modal/module/PanelEdit.jsx b/src/components/floor-plan/modal/module/PanelEdit.jsx
index dccedba2..5d38f9a8 100644
--- a/src/components/floor-plan/modal/module/PanelEdit.jsx
+++ b/src/components/floor-plan/modal/module/PanelEdit.jsx
@@ -14,7 +14,9 @@ import { useModule } from '@/hooks/module/useModule'
export const PANEL_EDIT_TYPE = {
MOVE: 'move',
+ MOVE_ALL: 'moveAll',
COPY: 'copy',
+ COPY_ALL: 'copyAll',
COLUMN_MOVE: 'columnMove',
COLUMN_COPY: 'columnCopy',
ROW_MOVE: 'rowMove',
@@ -29,7 +31,7 @@ export default function PanelEdit(props) {
const [direction, setDirection] = useState('up')
const { getMessage } = useMessage()
const canvas = useRecoilValue(canvasState)
- const { moduleMove, moduleCopy, moduleMultiMove, moduleMultiCopy } = useModule()
+ const { moduleMove, moduleCopy, moduleMultiMove, moduleMultiCopy, moduleMoveAll, moduleCopyAll } = useModule()
useEffect(() => {
if (canvas) {
@@ -44,9 +46,15 @@ export default function PanelEdit(props) {
case PANEL_EDIT_TYPE.MOVE:
moduleMove(length, direction)
break
+ case PANEL_EDIT_TYPE.MOVE_ALL:
+ moduleMoveAll(length, direction)
+ break
case PANEL_EDIT_TYPE.COPY:
moduleCopy(length, direction)
break
+ case PANEL_EDIT_TYPE.COPY_ALL:
+ moduleCopyAll(length, direction)
+ break
case PANEL_EDIT_TYPE.COLUMN_MOVE:
moduleMultiMove('column', length, direction)
break
diff --git a/src/hooks/module/useModule.js b/src/hooks/module/useModule.js
index 34f3f7bd..a4f50cbe 100644
--- a/src/hooks/module/useModule.js
+++ b/src/hooks/module/useModule.js
@@ -26,7 +26,8 @@ export const MODULE_INSERT_TYPE = {
}
export const MODULE_ALIGN_TYPE = {
- TOP: 'top',
+ VERTICAL: 'vertical',
+ HORIZONTAL: 'horizontal',
}
export function useModule() {
@@ -83,6 +84,162 @@ export function useModule() {
}
}
}
+ const moduleMultiMove = (type, length, direction) => {
+ if (canvas.getActiveObjects().length === 0) return
+ if (canvas.getActiveObjects().length > 1) {
+ swalFire({
+ title: '여러 개의 모듈을 선택할 수 없습니다.',
+ icon: 'error',
+ type: 'alert',
+ })
+ canvas.discardActiveObject()
+ return
+ }
+ const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
+ const modules = type === 'row' ? getRowModules(activeModule) : getColumnModules(activeModule)
+ const otherModules = getOtherModules(modules)
+ const objects = getObjects()
+ const moduleSetupSurface = canvas
+ .getObjects()
+ .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)[0]
+ let isWarning = false
+
+ modules.forEach((module) => {
+ const { top, left } = getPosotion(module, direction, length, false)
+ module.originPos = {
+ top: module.top,
+ left: module.left,
+ fill: module.fill,
+ }
+
+ module.set({ top, left })
+ module.setCoords()
+ canvas.renderAll()
+
+ if (otherModules.length > 0) {
+ if (isOverlapOtherModules(module, otherModules) || isOverlapObjects(module, objects) || isOutsideSurface(module, moduleSetupSurface)) {
+ isWarning = true
+ module.set({ fill: 'red' })
+ }
+ }
+ })
+
+ canvas.renderAll()
+ if (isWarning) {
+ swalFire({
+ title: getMessage('can.not.move.module'),
+ icon: 'error',
+ type: 'alert',
+ confirmFn: () => {
+ modules.forEach((module) => {
+ module.set({ top: module.originPos.top, left: module.originPos.left, fill: module.originPos.fill })
+ module.setCoords()
+ })
+ canvas.renderAll()
+ },
+ })
+ }
+ }
+
+ const moduleMoveAll = (length, direction) => {
+ const moduleSetupSurface = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
+ const modules = canvas.getObjects().filter((obj) => obj.surfaceId === moduleSetupSurface.id && obj.name === POLYGON_TYPE.MODULE)
+ const objects = getObjects()
+
+ let isWarning = false
+
+ modules.forEach((module) => {
+ const { top, left } = getPosotion(module, direction, length, false)
+ module.originPos = {
+ top: module.top,
+ left: module.left,
+ fill: module.fill,
+ }
+
+ module.set({ top, left })
+ module.setCoords()
+ canvas.renderAll()
+
+ if (isOverlapObjects(module, objects) || isOutsideSurface(module, moduleSetupSurface)) {
+ isWarning = true
+ module.set({ fill: 'red' })
+ }
+ })
+
+ canvas.renderAll()
+ if (isWarning) {
+ swalFire({
+ title: getMessage('can.not.move.module'),
+ icon: 'error',
+ type: 'alert',
+ confirmFn: () => {
+ modules.forEach((module) => {
+ module.set({ top: module.originPos.top, left: module.originPos.left, fill: module.originPos.fill })
+ module.setCoords()
+ })
+ canvas.renderAll()
+ },
+ })
+ }
+ }
+
+ const moduleCopyAll = (length, direction) => {
+ const moduleSetupSurface = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
+ const modules = canvas.getObjects().filter((obj) => obj.surfaceId === moduleSetupSurface.id && obj.name === POLYGON_TYPE.MODULE)
+ const objects = getObjects()
+ const copyModules = []
+ let copyModule = null
+ let isWarning = false
+ let moduleLength = 0
+ if (['up', 'down'].includes(direction)) {
+ modules.sort((a, b) => a.top - b.top)
+ moduleLength = Number(modules[modules.length - 1].top) + Number(modules[modules.length - 1].height) - Number(modules[0].top)
+ } else if (['left', 'right'].includes(direction)) {
+ modules.sort((a, b) => a.left - b.left)
+ moduleLength = Number(modules[modules.length - 1].left) + Number(modules[modules.length - 1].width) - Number(modules[0].left)
+ }
+
+ modules.forEach((module) => {
+ const { top, left } = getPosotion(module, direction, Number(length) + Number(moduleLength), false)
+ module.clone((obj) => {
+ obj.set({
+ parentId: module.parentId,
+ initOptions: module.initOptions,
+ direction: module.direction,
+ arrow: module.arrow,
+ name: module.name,
+ type: module.type,
+ length: module.length,
+ points: module.points,
+ surfaceId: module.surfaceId,
+ left,
+ top,
+ id: uuidv4(),
+ })
+ copyModule = obj
+ canvas.add(obj)
+ copyModules.push(obj)
+ obj.setCoords()
+ })
+ if (isOverlapObjects(copyModule, objects) || isOutsideSurface(copyModule, moduleSetupSurface)) {
+ isWarning = true
+ copyModule.set({ fill: 'red' })
+ }
+ canvas.renderAll()
+ })
+
+ if (isWarning) {
+ swalFire({
+ title: getMessage('can.not.copy.module'),
+ icon: 'error',
+ type: 'alert',
+ confirmFn: () => {
+ canvas.remove(...copyModules)
+ canvas.renderAll()
+ },
+ })
+ }
+ }
const moduleCopy = (length, direction) => {
if (canvas.getActiveObjects().length === 0) return
@@ -144,63 +301,6 @@ export function useModule() {
}
}
- const moduleMultiMove = (type, length, direction) => {
- if (canvas.getActiveObjects().length === 0) return
- if (canvas.getActiveObjects().length > 1) {
- swalFire({
- title: '여러 개의 모듈을 선택할 수 없습니다.',
- icon: 'error',
- type: 'alert',
- })
- canvas.discardActiveObject()
- return
- }
- const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
- const modules = type === 'row' ? getRowModules(activeModule) : getColumnModules(activeModule)
- const otherModules = getOtherModules(modules)
- const objects = getObjects()
- const moduleSetupSurface = canvas
- .getObjects()
- .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)[0]
- let isWarning = false
-
- modules.forEach((module) => {
- const { top, left } = getPosotion(module, direction, length, false)
- module.originPos = {
- top: module.top,
- left: module.left,
- fill: module.fill,
- }
-
- module.set({ top, left })
- module.setCoords()
- canvas.renderAll()
-
- if (otherModules.length > 0) {
- if (isOverlapOtherModules(module, otherModules) || isOverlapObjects(module, objects) || isOutsideSurface(module, moduleSetupSurface)) {
- isWarning = true
- module.set({ fill: 'red' })
- }
- }
- })
-
- canvas.renderAll()
- if (isWarning) {
- swalFire({
- title: getMessage('can.not.move.module'),
- icon: 'error',
- type: 'alert',
- confirmFn: () => {
- modules.forEach((module) => {
- module.set({ top: module.originPos.top, left: module.originPos.left, fill: module.originPos.fill })
- module.setCoords()
- })
- canvas.renderAll()
- },
- })
- }
- }
-
const moduleMultiCopy = (type, length, direction) => {
if (canvas.getActiveObjects().length === 0) return
if (canvas.getActiveObjects().length > 1) {
@@ -694,7 +794,64 @@ export function useModule() {
}
}
- const alignModule = (type) => {}
+ const alignModule = (type) => {
+ const moduleSetupSurface = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
+ const modules = canvas.getObjects().filter((obj) => obj.surfaceId === moduleSetupSurface.id && obj.name === POLYGON_TYPE.MODULE)
+ const objects = getObjects()
+ const top = Math.min(...modules.map((module) => module.top))
+ const left = Math.min(...modules.map((module) => module.left))
+ const moduleSurfacePos = {
+ top: Math.min(...moduleSetupSurface.points.map((point) => point.y)),
+ left: Math.min(...moduleSetupSurface.points.map((point) => point.x)),
+ }
+ const [height, width] = [bottom - top, right - left]
+ const verticalCenterLength = moduleSurfacePos.top + moduleSetupSurface.height / 2 - (top + height / 2)
+ const horizontalCenterLength = moduleSurfacePos.left + moduleSetupSurface.width / 2 - (left + width / 2)
+ let isWarning = false
+
+ canvas.discardActiveObject()
+ modules.forEach((module) => {
+ module.originPos = {
+ left: module.left,
+ top: module.top,
+ fill: module.fill,
+ }
+ if (type === MODULE_ALIGN_TYPE.VERTICAL) {
+ module.set({ top: module.top + verticalCenterLength })
+ } else if (type === MODULE_ALIGN_TYPE.HORIZONTAL) {
+ module.set({ left: module.left + horizontalCenterLength })
+ }
+
+ canvas.renderAll()
+ module.setCoords()
+ if (isOverlapObjects(module, objects) || isOutsideSurface(module, moduleSetupSurface)) {
+ isWarning = true
+ module.set({ fill: 'red' })
+ }
+ })
+ canvas.renderAll()
+ if (isWarning) {
+ swalFire({
+ title: getMessage('can.not.align.module'),
+ icon: 'error',
+ type: 'alert',
+ confirmFn: () => {
+ modules.forEach((module) => {
+ module.set({ top: module.originPos.top, left: module.originPos.left, fill: module.originPos.fill })
+ module.setCoords()
+ })
+ canvas.renderAll()
+ },
+ })
+ }
+ }
+
+ const modulesRemove = () => {
+ const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
+ const modules = canvas.getObjects().filter((obj) => obj.surfaceId === activeModule.surfaceId && obj.name === POLYGON_TYPE.MODULE)
+ canvas.remove(...modules)
+ canvas.renderAll()
+ }
const isOverlapOtherModules = (module, otherModules) => {
return otherModules.some(
@@ -765,11 +922,15 @@ export function useModule() {
return {
moduleMove,
moduleMultiMove,
+ moduleMoveAll,
moduleCopy,
moduleMultiCopy,
+ moduleCopyAll,
moduleColumnRemove,
moduleRowRemove,
moduleColumnInsert,
muduleRowInsert,
+ modulesRemove,
+ alignModule,
}
}
diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js
index 02896cb3..837c489a 100644
--- a/src/hooks/useContextMenu.js
+++ b/src/hooks/useContextMenu.js
@@ -1,7 +1,7 @@
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { canvasState, currentMenuState, currentObjectState } from '@/store/canvasAtom'
import { useEffect, useState } from 'react'
-import { MENU } from '@/common/common'
+import { MENU, POLYGON_TYPE } from '@/common/common'
import AuxiliarySize from '@/components/floor-plan/modal/auxiliary/AuxiliarySize'
import { usePopup } from '@/hooks/usePopup'
import { v4 as uuidv4 } from 'uuid'
@@ -40,6 +40,7 @@ import { useCanvasSetting } from './option/useCanvasSetting'
import { useGrid } from './common/useGrid'
import { useAdsorptionPoint } from './useAdsorptionPoint'
import { useRoofFn } from '@/hooks/common/useRoofFn'
+import { MODULE_ALIGN_TYPE, useModule } from './module/useModule'
export function useContextMenu() {
const canvas = useRecoilValue(canvasState)
@@ -66,6 +67,7 @@ export function useContextMenu() {
const commonTextFont = useRecoilValue(fontSelector('commonText'))
const { settingsData, setSettingsDataSave } = useCanvasSetting()
const { swalFire } = useSwal()
+ const { alignModule } = useModule()
const { removeRoofMaterial, removeAllRoofMaterial } = useRoofFn()
const currentMenuSetting = () => {
@@ -691,36 +693,38 @@ export function useContextMenu() {
])
break
case 'moduleSetupSurface':
- case 'dimensionLineText':
+ case 'roof':
setContextMenu([
[
{
id: 'moduleVerticalCenterAlign',
name: getMessage('contextmenu.module.vertical.align'),
+ fn: () => alignModule(MODULE_ALIGN_TYPE.VERTICAL),
},
{
id: 'moduleHorizonCenterAlign',
name: getMessage('contextmenu.module.horizon.align'),
- },
- {
- id: 'moduleLeftAlign',
- name: getMessage('contextmenu.module.left.align'),
- },
- {
- id: 'moduleRightAlign',
- name: getMessage('contextmenu.module.right.align'),
- },
- {
- id: 'moduleUpAlign',
- name: getMessage('contextmenu.module.up.align'),
- },
- {
- id: 'moduleDownAlign',
- name: getMessage('contextmenu.module.down.align'),
+ fn: () => alignModule(MODULE_ALIGN_TYPE.HORIZONTAL),
},
{
id: 'moduleRemove',
name: getMessage('contextmenu.module.remove'),
+ fn: () => {
+ const moduleSetupSurface = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
+ const modules = canvas.getObjects().filter((obj) => obj.surfaceId === moduleSetupSurface.id && obj.name === POLYGON_TYPE.MODULE)
+ canvas.remove(...modules)
+ canvas.renderAll()
+ },
+ },
+ {
+ id: 'moduleMove',
+ name: getMessage('contextmenu.module.move'),
+ component: ,
+ },
+ {
+ id: 'moduleCopy',
+ name: getMessage('contextmenu.module.copy'),
+ component: ,
},
{
id: 'moduleCircuitNumberEdit',