diff --git a/B06_Section/B06_Section_UI_Adjust_Dock.ts b/B06_Section/B06_Section_UI_Adjust_Dock.ts index 79772480..ea4d76e7 100644 --- a/B06_Section/B06_Section_UI_Adjust_Dock.ts +++ b/B06_Section/B06_Section_UI_Adjust_Dock.ts @@ -21,20 +21,6 @@ export function setAdjustSideSlots(next: { inlet: HTMLElement; outlet: HTMLEleme sideSlots = next; } -/** 지금 붙는 사본이 **자동 선택**(카드를 골라 대표 벽이 딸려 온 경우)인가. - * 자동이면 그룹 강조를 켜지 않는다 — 강조는 도면에서 구조물을 직접 고를 때만 - * 쓴다(2026-08-29 사용자 지시). */ -let autoAdopt = false; - -export function withAutoAdopt(run: () => void): void { - autoAdopt = true; - try { - run(); - } finally { - autoAdopt = false; - } -} - /** 이식 자리가 지금 화면에 서 있는지 — 숨겨진 그룹(다른 시설)이면 옮기지 않는다. */ function slotUsable(target: HTMLElement | undefined): target is HTMLElement { if (!target) return false; @@ -67,8 +53,8 @@ function relocateSideRows(panelRoot: HTMLElement): void { if (row.classList.contains("is-hidden")) return; target.append(row); }); - // 도면에서 직접 고른 구조물만 그룹 테두리로 알린다(2026-08-29 사용자 지시 3). - if (!autoAdopt) target.closest("fieldset")?.classList.add("is-active"); + // 고른 구조물이 어느 쪽인지 그룹 테두리로 알린다(2026-08-29 사용자 지시 3). + target.closest("fieldset")?.classList.add("is-active"); } function ensureDock(): void { diff --git a/B06_Section/B06_Section_UI_Page.ts b/B06_Section/B06_Section_UI_Page.ts index f96a600a..7e9bcad6 100644 --- a/B06_Section/B06_Section_UI_Page.ts +++ b/B06_Section/B06_Section_UI_Page.ts @@ -46,9 +46,9 @@ import { staleDesignChainages } from "./B06_Section_UI_Section_Common"; import { createStandardPanel, type StandardPanelController } from "./B06_Section_UI_Standard_Panel"; import { createB06StructuresPanel, + isWallSelecting, wireStructureSelection, } from "./B06_Section_UI_Page_Structures_Panel"; -import { withAutoAdopt } from "./B06_Section_UI_Adjust_Dock"; import "./B06_Section_UI_Style.css"; import "./B06_Section_UI_Style_Cross.css"; import "./B06_Section_UI_Style_Cross_Controls.css"; @@ -471,7 +471,6 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { stationControls, () => sectionDetail, structuresPanel, - (chainageM) => sectionView.refreshCard(chainageM), ); // 횡단도(카드) 자체를 골라도 그 측점 구조물 정보를 폼에 올린다(2026-08-29 사용자). // 연동으로 옆에서 넘어온 카드는 **소유 측점** 시설을 보여 준다. @@ -486,27 +485,14 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { const owner = stationControls.structureSpan.ownerOf(target); structuresPanel.showAtChainage(owner?.chainage_m ?? target.chainage_m); structureSelection.syncInletStructure(); - selectDefaultWall(owner ?? target); + // 카드만 고른 경우엔 구조물(벽·구체) 선택을 비운다 — 조정창이 저절로 뜨면 안 된다 + // (2026-08-29 사용자). 벽을 찍어 카드가 딸려 선택된 경우는 건드리지 않는다. + if (!isWallSelecting() && stationControls.revetOffset.selectedFor(target)) { + stationControls.revetOffset.select(target.chainage_m, null); + sectionView.refreshCard(target.chainage_m); + } }); - /** - * 시설을 폼에 올릴 때 **대표 벽**(유출 기준벽, 없으면 유입)을 함께 고른다 — - * 단 수·옵션 행은 고른 벽에 딸린 것이라 벽이 없으면 유입구·유출구 그룹이 빈다 - * (2026-08-29 사용자 보고). 이미 고른 벽이 있으면 건드리지 않는다. - */ - function selectDefaultWall(section: NonNullable["cross_sections"][number]) { - const culvert = section.culvert; - if (!culvert) return; - if (stationControls.revetOffset.selectedFor(section)) return; - const key = culvert.outlet ? "outlet" : culvert.inlet ? "inlet" : null; - if (!key) return; - // 자동으로 딸려 온 선택이라 그룹 강조는 켜지 않는다(2026-08-29 사용자 지시). - withAutoAdopt(() => { - stationControls.revetOffset.select(section.chainage_m, key); - sectionView.refreshCard(section.chainage_m); - }); - } - // 메인 영역: 종·횡단 도면(sectionView) 또는 안내 메시지를 표시한다. const mainArea = document.createElement("div"); mainArea.className = "b06-profile__main"; diff --git a/B06_Section/B06_Section_UI_Page_Structures_Panel.ts b/B06_Section/B06_Section_UI_Page_Structures_Panel.ts index 6645ee5a..e6079639 100644 --- a/B06_Section/B06_Section_UI_Page_Structures_Panel.ts +++ b/B06_Section/B06_Section_UI_Page_Structures_Panel.ts @@ -24,12 +24,7 @@ import { } from "../B05_Profile/B05_Profile_Api_Structures"; import { fetchDetailPipePoints } from "../B04_PreProcess/B04_PreProcess_Api_Fetch"; import { showToast } from "@ui/ui_template_elements"; -import { - adjustDockRoot, - resetAdjustDock, - setAdjustSideSlots, - withAutoAdopt, -} from "./B06_Section_UI_Adjust_Dock"; +import { adjustDockRoot, resetAdjustDock, setAdjustSideSlots } from "./B06_Section_UI_Adjust_Dock"; import type { SectionDetailResponse } from "./B06_Section_Api_Fetch"; import type { StationControls } from "./B06_Section_UI_Page_Station_Controls"; @@ -208,12 +203,26 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc * 구조물의 **소유 측점** 시설을 좌측 폼에 올린다(2026-08-29 일원화 3단계). * 제어 객체의 select를 감싸기만 한다 — 조작·저장 경로는 그대로다. */ +/** 지금 처리 중인 선택이 **도면에서 벽·구체를 찍은 것**인가 — 카드 선택 리스너가 + * 이 값으로 "카드만 고른 경우"를 가려낸다(2026-08-29 사용자: 측점 선택 때 구조물이 + * 자동으로 골라지면 안 된다). 같은 턴에서만 참이다. */ +let wallSelecting = false; + +export function isWallSelecting(): boolean { + return wallSelecting; +} + +function markWallSelecting(): void { + wallSelecting = true; + queueMicrotask(() => { + wallSelecting = false; + }); +} + export function wireStructureSelection( stationControls: StationControls, detail: () => SectionDetailResponse | null, panel: B06StructuresPanel, - /** 대표 벽으로 되돌릴 때 카드를 다시 그린다 — 없으면 되돌리지 않는다. */ - refreshCard?: (chainageM: number) => void, ): { syncInletStructure: () => void } { const ownerChainageOf = (chainageM: number): number => { const sectionAt = detail()?.cross_sections.find( @@ -240,36 +249,21 @@ export function wireStructureSelection( const origRevet = stationControls.revetOffset.select; stationControls.revetOffset.select = (chainageM, key) => { + markWallSelecting(); origRevet(chainageM, key); - if (key) { - panel.showPipeAt(ownerChainageOf(chainageM)); - syncInletStructure(); - return; - } - // 선택을 풀어도 폼의 단 수·옵션 행은 남아야 한다 — 그 행들은 벽에 딸려 있으므로 - // 대표 벽으로 조용히 되돌린다(강조만 꺼진다, 2026-08-29 사용자 지시). - const target = detail()?.cross_sections.find( - (entry) => Math.abs(entry.chainage_m - chainageM) < 0.01, - ); - const fallback = target?.culvert ? (target.culvert.outlet ? "outlet" : "inlet") : null; - if (!fallback || !refreshCard) { - panel.showPipeAt(null); - return; - } - withAutoAdopt(() => { - origRevet(chainageM, fallback); - refreshCard(chainageM); - }); - panel.showPipeAt(ownerChainageOf(chainageM)); - syncInletStructure(); + panel.showPipeAt(key ? ownerChainageOf(chainageM) : null); + if (key) syncInletStructure(); }; + const origFord = stationControls.ford.select; stationControls.ford.select = (chainageM, role) => { + markWallSelecting(); origFord(chainageM, role); panel.showPipeAt(role ? chainageM : null); }; const origBox = stationControls.box.select; stationControls.box.select = (chainageM, role) => { + markWallSelecting(); origBox(chainageM, role); panel.showPipeAt(role ? chainageM : null); };